JS asynchronous topic

Asynchronous topics: promise and async, await

1. synchronous and asynchronous

Synchronous and asynchronous: synchronous and asynchronous message is a notification mechanism

  • Synchronization: A calls B, B deal with the results obtained, before returning to A. A In the process, the results have been pending B, and before did not get results, you need to A (caller) has been waiting call and confirm whether to return results, get results, and then continue down. Before doing a thing, did not get the results, it has been waiting for this, wait until there are results, and then do the following things
  • Asynchronous: A calls B, without waiting for the result of B, A or B is notified through callback function to handle status notification. Do one thing, do not wait for the results of things, and then went busy with anything else, with the result, and then tell me by the state, or processed through the callback function. Such as timers, etc.

2.ES6 Promise objects

Promise objects ES6 is a constructor to generate Promise instance.

The so-called Promise object is to represent a certain future events (usually an asynchronous operation) will take place.

Its advantage is that, with the object Promise, can be asynchronous operation to synchronous operation flow express avoided deeply nested callback

  • Promise of three states: pending, resolve and reject
  • then the method and try / catch - image loading

then the return value will return a new Promise objects, but the state will have several situations:

  1. - then the callback function does not return a value, then a status will be returned: promise of objects resolved
  2. - then the value of the callback function returns non-promise and then returns a status of: the promise resolved the object, the return value will additionally, then passed to the next
  3. - then the callback function return value is the promise the object, then the object directly back to this promise, the specific state can be defined by our own values ​​of specific delivery also defined by our own

Three states 3.Promise object

Promise of three states: pending, resolved and rejected

  1. When you create a Promise object, that does not perform a successful nor unsuccessful, the status is pending;
  2. When you create a Promise object, if the object is a method executed successfully resolve (), then the state returns resolved;
  3. Promise When creating an object, if the object is a method fails Reject (), then the state returns Rejected, and error;
  4. When you create an object or by Promise, whether successful call interface to obtain response status of Promise
    let p = new Promise((resolve,reject)=>{
        resolve("执行成功");
        // reject("执行失败");
    });

    //创建Promise对象时,即没有执行成功也没有执行失败,则状态为pending
    // console.log(p);//Promise {<pending>}

    //创建Promise对象时,如果对象中是执行成功方法resolve,则返回状态为resolved
    console.log(p);//Promise {<resolved>: "执行成功"}
    
    //创建Promise对象时,如果对象中是执行失败方法reject,则返回状态为rejected,且报错
    // console.log(p);//Promise {<rejected>: "执行失败"}

then the object method 4.Promise

  1. Then the method has two parameters, are functions;
  2. Then the first parameter representation of a method performed successfully executed;
  3. The second parameter representation then the method fails after execution;
  4. then the method can be called multiple (chain call), then on a return value of a then decide success or failure of the implementation of the method;
    let p = new Promise((resolve,reject)=>{
        // resolve("执行成功");
        reject("执行失败");
    });

    //
    p.then(info=>{
        //第一个参数,执行成功时调用
        console.log(info);//执行成功
    },msg=>{
        //第二个参数,执行失败时调用
        console.log(msg);//执行失败
    });

Example: Picture Download

If the picture is downloaded successfully take the first method, if the picture download fails to go the second method

    let p = new Promise((resolve,reject)=>{
        let img = new Image();
        img.src = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1565026842061&di=796e2653d34dfe2c98a7b8538fae2aca&imgtype=0&src=http%3A%2F%2Fimages.cnblogs.com%2Fcnblogs_com%2Fidotnet8%2Fchina.gif";
        
        img.onload = function(){
            resolve("图片加载成功");
        };
        img.onerror = function(){
            reject("图片加载失败");
        };
    });

    //
    p.then(success=>{
        console.log(success);//图片加载成功
    },error=>{
        console.log(error);//图片加载失败
    });

then the return value will return a new Promise objects, but the state will have several situations:

  1.  then the callback function does not return a value , then a status will be returned: promise of objects resolved. If the first method does not return a value then, is whether this then taking the success or failure of the method will not affect the method of execution of the next then .
  2.  callback function then returns the value of the non-promise , then it will return a status of: the promise resolved the object, the return value will additionally, then passed to the next
  3. then callback function return value is a self-promise of object definitions , then return to this promise directly target specific state can be defined by our own values of specific delivery also defined by our own (at this time if the definition of the object returned from Promise resolve, success information will be passed to the next then the first method; if it returns from the object definition Promise reject, sends a failure message is transmitted to the second method, then the next).
  •  When then no return value (time then no return value, then all of the default method performed simultaneously): then it will return a status: promise of objects resolved
    let p = new Promise((resolve,reject)=>{
        resolve("成功");
    });

    //then返回值一:如果then 方法没有返回值,就会返回一个状态为resolved的promise对象(即没有返回值默认走第一个成功的函数)
    p.then(success=>{
        console.log(success);//成功 第一个then方法没有返回值,所以默认走这个成功的方法
    },error=>{
        console.log(error);
    }).then(info=>{
        console.log(info);//undefined 由于第一个then没有返回值,而第二个then是根据第一个then的返回值接收信息的,所以info为undefined
    });
  • then returns a value, but the value is non-return to promise: then returns a status of: the promise resolved the object, the return value will additionally, then passed to the next
    let p = new Promise((resolve,reject)=>{
        resolve("成功");
    });

    //then返回值二:当then方法有返回值,但返回值时非promise对象时,直接将返回值传递给下一个then
    p.then(success=>{
        console.log(success);//成功
        return success;
    },error=>{
        console.log(error);
    }).then(info=>{
        console.log(info);//成功 当then方法有返回值,但返回值时非promise对象时,直接将返回值传递给下一个then,所以这里的then方法得到的信息时第一个then的返回值
    });
  • then callback function return value is the promise the object, then the object directly back to this promise, the specific state can be defined by our own values ​​of specific delivery also defined by our own
  1.  At this time, if the object is a custom return Promise resolve, success information will be passed to the next then the first method of
  2. If the object is a custom return Promise reject, it will fail information to a second method, then the next
    let p = new Promise((resolve,reject)=>{
        resolve("成功");
    });

    //then返回值三:当then方法有返回值,且返回值为Promise对象时,then方法直接返回这个Promise对象,具体的状态和值由我们自己决定
        // 此时如果自定义的Promise对象返回resolve,会将成功信息传递给下一个then的第一个方法
        // 如果自定义的Promise对象返回reject,会将失败信息传递给下一个then的第二个方法
    p.then(success=>{
        return new Promise((resolve,reject)=>{
            // resolve("第一个then方法成功");
            reject("第一个then方法失败");
        });
    },error=>{
        console.log(error);
    }).then(succMsg=>{
            console.log(succMsg);
    },errMsg=>{
        console.log(errMsg);
    });

5.Async function and await

  1. async functions and await methods, using various methods must await the successful execution and in the case dependent.
  2. If the async and await function method, wherein a await execution fails, then the program is no longer performed.
  3. Await the plurality of methods, can be omitted await a final

Demand: three data request with a request dependent on 2, 3 2 requests the request. I.e., a request can only be executed after execution request 2 is completed, the request must be performed over 2 to execute the request 3

    //Promise异步即以同步的方式实现异步
    async function fn(){
        await new Promise((resolve,reject)=>{
            setTimeout(function(){
                console.log("请求3");
                resolve();
            },1000);
        });
        await new Promise((resolve,reject)=>{
            setTimeout(function(){
                console.log("请求2");
                resolve();
            },1000);
        });
        await new Promise((resolve,reject)=>{
            setTimeout(function(){
                console.log("请求1");
                resolve();
            },1000);
        });
    }

    fn();

async functions and await method in which a await execution fails, then the program will no longer execute:

The second reject following method represents await execution fails, the execution fails, the request will not proceed 1

    async function fn(){
        await new Promise((resolve,reject)=>{
            setTimeout(function(){
                console.log("请求3");
                resolve();
            },1000);
        });
        await new Promise((resolve,reject)=>{
            setTimeout(function(){
                console.log("请求2");
                reject();
            },1000);
        });
        await new Promise((resolve,reject)=>{
            setTimeout(function(){
                console.log("请求1");
                resolve();
            },1000);
        });

Constructor method in 6.Promise: resolve (), reject (), all (), race ()

  1. Promise.resolve () returns status resolved, and the success information customizable
  2. Promise.reject () returns status rejected, failure information and can customize
  3. Promise.all ([p1, p2, p3]) function successfully if all promise, will perform. Promise.all ([p1, p2, p3]) return value, regardless of the method and then call then there is no method of execution failures, are taking the first parameter (success)
  4. Promise.race () regardless of the success or failure of execution, which method to perform the return which method's return value. When Promise.race ([p1, p2, p3]) Returns the value of the method, and then call the method then, regardless of which method succeeded or failed, we are taking the first argument then the method of (successful)

6.1 Promise.resolve () and reject () method :

{
   let a = Promise.resolve("成功");
   console.log(a);//Promise {<resolved>: "成功"}

try {
    let b = Promise.reject("失败");
   console.log(b);//Promise {<rejected>: "失败"}并且报错
    throw "执行出错";
} catch (error) {
    console.log(error);//执行出错
}

Functions 6.2 Promise.all ([p1, p2, p3]) are all promise success, will perform:

Promise.all ([p1, p2, p3]) return value, regardless of the method and then call then there is no method of execution failures, are taking the first parameter (success)

    let p1 = new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve("p1执行成功");
        },1000);
    });

    let p2 = new Promise((resolve,reject)=>{
        setTimeout(function(){
            // resolve("p2执行成功");
            resolve("p2执行失败");
        },1000);
    });

    let p3 = new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve("p3执行成功");
        },1000);
    });
    //Promise.all([p1,p2,p3])只有所有的promise对象都是返回resolved状态,才会成功
    let allP = Promise.all([p1,p2,p3]);
    console.log(allP);

    //Promise.all([p1,p2,p3])的返回值,再调用then方法无论有没有执行失败的方法,都是走第一个参数(成功)
    allP.then(msg=>{
        console.log("成功");
        // console.log(msg);//(3) ["p1执行成功", "p2执行成功", "p3执行成功"]
        console.log(msg);//(3) ["p1执行成功", "p2执行失败", "p3执行成功"]
        
    },info=>{
        console.log("失败");
    });

6.3Promise.race () or whether failure to perform successful implementation of the return which method first of which method's return value

When Promise.race ([p1, p2, p3]) Returns the value of the method, and then call the method then, regardless of which method succeeded or failed, we are taking the first argument then the method of (successful)

    //Promise.race([p1,p2,...])方法中那个方法执行的最快,就返回哪个方法的返回值
    let p1 = new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve("p1执行成功");
        },1000);
    });

    let p2 = new Promise((resolve,reject)=>{
        setTimeout(function(){
            // resolve("p2执行成功");
            resolve("p2执行失败");
        },500);
    });

    let p3 = new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve("p3执行成功");
        },3000);
    });
    let raceP = Promise.race([p1,p2,p3]);
    console.log(raceP);

    //Promise.race([p1,p2,p3])方法的返回值,再调用then方法时,无论其中的方法执行成功还是失败,都是走then方法的第一个参数(成功)
    raceP.then(msg=>{
        console.log("成功");//成功
        console.log(msg);//p2执行失败
        
    },info=>{
        console.log("失败");
        console.log(info);
    });

7. Generator function and iterators

Underlying async await Generator is through gradual evolution over. Now, with async await method, basically Generator has been rarely used. But some underlying framework may be used.

7.1 Iteration

  1. Iteration protocol: specifies the logical iteration and implementation of
  2. Iterator: iterative implementation specific logic
  3. Iterative objects: objects that can be iterated to - achieve [Symbol.iterator] Method
  4. Iteration statements
  • for ... in: iterator object in the original sequence may be inserted enumerated attribute ( iterative array is the key value )
  • for ... of: iterative embodied according to the object data object is iterating ( iterative value is an array of values )
  • Objects can be used for ... in loop, but can not be used for ... of the cycle, because the object is not iterable, there is no method to achieve Symbol.iterator

Iterators implement the principle [Symbol.iterator]:

obj[Symbol.iterator] = function(){
    return {
        next(){
            return {
                value: this.i++, 
                done: false 
            }
        }
    }
}

for ... in iteration is key array of values :

    // for ...in 迭代的是数组的key值
    var arr = [1,2,3,4,5];
    for(var index in arr){
        console.log(index);//0,1,2,3,4
    }

for ... of realization iteration, iteration value is an array of values :

    // for ...of 迭代的是数组的value值
    var arr = [1,2,3,4,5];
    for(var val of arr){
        console.log(val);//1,2,3,4,5
    }

Objects can be used for ... in loop, but can not be used for ... of the cycle, because the object is not iterable, not implemented Symbol.iterator method:

//对象使用for ...in循环
    let obj = {
        a:1,
        b:2
    };
    for(let o in obj){
        console.log(o);//a b
    }

 Object uses for ... of direct loop error:

//对象使用for ...of循环
    let obj = {
        a:1,
        b:2
    };
    for(let val of obj){
        console.log(val);//for...of迭代.html:22 Uncaught TypeError: obj is not iterable
    }

 

7.2 iterators implement the principle [Symbol.iterator]

  • Iteration protocol: according to what is circulated, the loop can get something, you can define your own;
  • It owns the iterator is iterable;
  • Iteration implements the principle is fixed;
    let obj = {
        a:1,
        b:2
    };

    //自定义实现迭代器
    obj[Symbol.iterator] = function(){
        //注意获取values和keys的方法时Object构造函数下的方法
        let vals = Object.values(obj);
        let keys = Object.keys(obj);
        
        let index = 0;
        return {
            next(){
                if(index>=keys.length){
                    return {
                        done:true
                    }
                }else{
                    //只想得到value值
                    // return {
                    //     value: vals[index++],
                    //     done:false
                    // }

                    //只想得到key值
                    // return {
                    //     value: keys[index++],
                    //     done:false
                    // }

                    //value值和key值想同时得到,就可以将value写成对象
                    return {
                        value: {
                            keys:keys[index],
                            //获取values时拖过keys获取,不要直接通过vals获取
                            values:obj[keys[index++]]
                        },
                        done:false
                    }
                }
            }
        };
    };

    for(let val of obj){
        console.log(val)
    }

result:

 

7.3Generator function

Formally, Generator is a common function, but there are two features.

  1. First, function between command and function names have an asterisk .
  2. Second, the functions that use the yield statement, each walker member definition, i.e. different internal states
  3. After calling Generator function will not be executed immediately method, and call the next Generator function () will be executed

### Generator Syntax

// Generator 语法
    function* gen() { 
        yield 1;
        yield 2;
        yield 3;
    }

    //调用Generator函数不会立即执行
    let g = gen(); 
    console.log(g.next());//{value: 1, done: false}

 7.4Generator asynchronous function and associated

Since the implementation of Generator functions :

    co function: custom automation generator function caller . Asynchronous execution before completion of execution of a next asynchronous function is determined on the

    function*fn(){
        yield new Promise((resolve,reject)=>{
            setTimeout(()=>{
                console.log("a");
                resolve(1);
            },500);
        });
        yield new Promise((resolve,reject)=>{
            setTimeout(()=>{
                console.log("b");
                resolve(2);
            },500);
        });
        yield new Promise((resolve,reject)=>{
            setTimeout(()=>{
                console.log("c");
                resolve(3);
            },500);
        });
    }

    co(fn);
    function co(fn){
        let f = fn();
        next();
        function next(msg){
            let result = f.next();
            if(!result.done){//done为true时表示走完了
                result.value.then(info=>{
                    console.log(info,msg);//data表示上一步的返回信息
                    //上一个异步走完了,再执行下一个异步
                    next(info);
                });
            }
            
        }
        
    }

result:

 

8. achieved by chain animation Promise (three ways)

Achieved in three ways: callback hell (repeated call); then the method of Promise; async / await method of Promise

Demand: Custom packaging simple animation animation framework, so that box from left to right, then top to bottom, then from right to left, then moved 200px from the bottom up.

8.1 callback hell way

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>链式动画</title>
    <style>
        body {
            margin: 0px;
            padding: 0px;
            position: relative;
        }
        #box {
            width: 100px;
            height: 100px;
            background: red;
            position: absolute;
            left: 0;
            top: 0;
        }
    </style>
</head>
<body>
<div id="box"></div>
<script>
{
    //需求:自定义封装动画简易动画框架,让box 从左到右,再从上到下,再从右向左,再从下往上移动200px。

    let box = document.querySelector("#box");
    //需要给定参数,哪个元素,方向,移动到哪个位置
    let move =(el,attr,target,cb)=>{
        //获取元素起始位置
        let start = parseFloat(getComputedStyle(el)[attr]);
        //动画运动时,left或top有可能为往回走,就会是负方向
        let dir = (target-start)/Math.abs(start-target);
        let speed = 5;//元素移动的速度

        let count = 0;//动画帧编号,用于取消requestAnimationFrame

        //通过JS动画帧requestAnimationFrame让元素动起来
        cancelAnimationFrame(count);
        count = requestAnimationFrame(goTarget);
        function goTarget(){
            start += speed*dir;
            
            //注意这里使用点会有问题
            el.style[attr] = start + 'px';
                    
            //如果start等于了target就代表已经走完了,否则继续动画
            if(start == target){
                cancelAnimationFrame(count);
                cb&&cb();
            }else{
                //注意动画编号在动画帧再次调用时仍然要记录
                count = requestAnimationFrame(goTarget);
            }
        }        
        
    }

    //回调地狱
    //从左到右
    move(box,"left",200,function(){
        //从上到下
        move(box,"top",200,function(){
            // 从右向左
            move(box,"left",0,function(){
                move(box,"top",0,null);
            });
        });
    });
}
</script>
</body>
</html>

8.2 then the method to achieve chain animation

    //需求:自定义封装动画简易动画框架,让box 从左到右,再从上到下,再从右向左,再从下往上移动200px。

    let box = document.querySelector("#box");
    //需要给定参数,哪个元素,方向,移动到哪个位置
    let move =(el,attr,target)=>{
        //获取元素起始位置
        let start = parseFloat(getComputedStyle(el)[attr]);
        //动画运动时,left或top有可能为负
        let dir = (target-start)/Math.abs(start-target);
        let speed = 5;//元素移动的速度

        let count = 0;//动画帧编号,用于取消requestAnimationFrame

        //  使用Promise then方法必须返回Promise对象
        return new Promise((resolve,reject)=>{
            //通过JS动画帧requestAnimationFrame让元素动起来
            cancelAnimationFrame(count);
            count = requestAnimationFrame(goTarget);
            function goTarget(){
                start += speed*dir;
                console.log(start);
                
                //注意这里使用点会有问题
                el.style[attr] = start + 'px';
                        
                //如果start等于了target就代表已经走完了,否则继续动画
                if(start == target){
                    cancelAnimationFrame(count);
                    resolve();
                }else{
                    //注意动画编号在动画帧再次调用时仍然要记录
                    count = requestAnimationFrame(goTarget);
                }
            }        
        });
        
    }

    //使用Promise 的then方法实现动画异步执行
    move(box,"left",200)
    .then(item=>{
        //使用Promise 的then方法时,必须有return才能异步执行,否则全部then方法会同步执行
        return move(box,"top",200);
    })
    .then(item=>{
        return move(box,"left",0);
    }).then(item=>{
        move(box,"top",0);
    });

8.3 async await method to achieve chain animation

    //需求:自定义封装动画简易动画框架,让box 从左到右,再从上到下,再从右向左,再从下往上移动200px。

    let box = document.querySelector("#box");
    //需要给定参数,哪个元素,方向,移动到哪个位置
    let move =(el,attr,target)=>{
        //获取元素起始位置
        let start = parseFloat(getComputedStyle(el)[attr]);
        //动画运动时,left或top有可能为负
        let dir = (target-start)/Math.abs(start-target);
        let speed = 5;//元素移动的速度

        let count = 0;//动画帧编号,用于取消requestAnimationFrame

        //  使用Promise then方法必须返回Promise对象
        return new Promise((resolve,reject)=>{
            //通过JS动画帧requestAnimationFrame让元素动起来
            cancelAnimationFrame(count);
            count = requestAnimationFrame(goTarget);
            function goTarget(){
                start += speed*dir;
                
                //注意这里使用点会有问题
                el.style[attr] = start + 'px';
                        
                //如果start等于了target就代表已经走完了,否则继续动画
                if(start == target){
                    cancelAnimationFrame(count);
                    resolve();
                }else{
                    //注意动画编号在动画帧再次调用时仍然要记录
                    count = requestAnimationFrame(goTarget);
                }
            }        
        });
        
    }

    //使用Promise 的then方法实现动画异步执行
    async function runMove(){
        await move(box,"left",200);
        await move(box,"top",200);
        await move(box,"left",0);
        await move(box,"top",0);//最后一个await可以不写
    }
    runMove();

 

Published 95 original articles · won praise 115 · views 120 000 +

Guess you like

Origin blog.csdn.net/qq_34569497/article/details/98392151