JS asynchronous function sequential execution summary

Purpose: Summary
Application scenario: Part of the data is to wait for individual interface requests to return data before making a call request
**1.** Call function2 after the execution of function1 is completed, but if there are more nested call levels, a "callback" will appear Hell', as follows:

//普通的
function A(callback){
    
    
    console.log("I am A");
    callback();  //调用该函数
}

function B(){
    
    
   console.log("I am B");
}

A(B);
//回调地狱
    function fun1(a) {
    
    
       a();
    }
    function fun2(b) {
    
    
       b();
    };
    function fun3(c) {
    
    
       c();
    };
    function fun4(d) {
    
    
       d();
    };
    function fun5(e) {
    
    
       e();
    };
    function fun6() {
    
    
       console.log("6");
    }
    fun1(() => {
    
    
    fun2(() => {
    
    
        fun3(() => {
    
    
        fun4(() => {
    
    
            fun5(() => {
    
    
            fun6();
            })
        })
        })
    })
    });

2. ES6's Promise
Promise can solve the above-mentioned callback hell problem, and clearly express that the callback
Promise object has the following two characteristics.

(1) The state of the object is not affected by the outside world. The Promise object represents an asynchronous operation and has three states: pending (in progress), fulfilled (successful) and rejected (failed). Only the result of an asynchronous operation can determine which state is currently in, and no other operation can change this state. This is also the origin of the name Promise, which means "promise" in English, which means that it cannot be changed by other means.

(2) Once the state changes, it will not change again, and this result can be obtained at any time. There are only two possibilities for the state of the Promise object to change: from pending to fulfilled and from pending to rejected. As long as these two situations occur, the state will be frozen and will not change anymore. This result will always be maintained. At this time, it is called resolved. If the change has occurred, and you add a callback function to the Promise object, you will get this result immediately. This is completely different from an event. The feature of an event is that if you miss it, you can listen to it and you will get no results.

const promise = new Promise(function(resolve, reject) {
    
    
  // ... some code

  if (/* 异步操作成功 */){
    
    
    resolve(value);
  } else {
    
    
    reject(error);
  }
});
//基于Promise 封装ajax
function ajax({
    
    url:"",type:"get",dataType:"json"}) {
    
    
    return new Promise((resolve,reject)=>{
    
    
        let xhr=new XMLHttpRequest();
        xhr.open(type,url,true);
        //后台给返回的数据类型,一般都是json
        xhr.responseType=dataType;
        xhr.onload=function(){
    
    
            if(xhr.code ==200 && xhr.readyState ==4){
    
    
                //成功调用
                resolve(xhr.response)
            }
        }
        xhr.onerror=function(err){
    
    
            //失败调用
            reject(err)
        }
        xhr.send();
    })
}
//基于promise封装的axios
export const get/post = (url,params)=>{
    
    
    params = params || {
    
    };
    return new Promise((resolve,reject)=>{
    
    
        // axios自带 get 和 post 方法
        $http.get/post(url,{
    
    
            params,
        }).then(res=>{
    
    
            if(res.data.status===0){
    
    
                resolve(res.data);
            }else{
    
    
                alert(res.data.msg)
            }
        }).catch(error=>{
    
    
            alert('网络异常');
        })
    })
}
//Eg:vue项目中所用到的基于promise原理实现的请求接口
    handlerClose(id,k) {
    
    
         this.$axios({
    
    
          method:'post',
          headers: {
    
     //请求头
           'Content-Type': 'application/json',
           "Authorization": 'Bearer '+this.accessToken //token换成从缓存获取
        },
          url:this.videourl+'v1/live/end-live',
          data:{
    
    
            liveId:id
          }
        }).then( res =>{
    
    
            if(res.data.code==200){
    
    
              this.$toast('关闭成功');
              this.list.splice(k,1);
            }else{
    
    
              this.$toast(res.data.message);
            }
        }).catch( e =>{
    
    
          let code=e.response.status;
          if(code==401){
    
    
             this.islogin=true;
          }
        })
    },
     

3. ES6 Generator
Generator (generator) is a special kind of function. The difference from ordinary function declaration is that a * sign is added. A generator function can be obtained in the following two ways:

//2种基础写法
function* helloWorldGenerator{
    
    
  //to do something
}
function *helloWorldGenerator{
    
    
  //to do something
}

Iterator (iterator): When we instantiate a generator function, this instance is an iterator. You can use the next() method to start the generator and control whether the generator is executed.
Yield/next: This is a good pair of friends who control the order of code execution.
Through the yield statement, the execution of the code can be suspended inside the generator function to make it hang. At this time, the generator function is still running and active, and its internal resources will be retained, but it is in a suspended state.
Calling the next() method on the iterator can cause the code to continue execution from where it was paused.

Eg://next()第一次调用是启动生成器 
   function *helloWorldGenerator(){
    
    
    console.log('第一次打印starting helloWorldGenerator()');
    yield;
    console.log('第二次打印starting helloWorldGenerator()');
    yield;
    console.log('第三次打印starting helloWorldGenerator()');
	let _self=helloWorldGenerator();
	_self.next();
	_self.next();
	_self.next();
	/*
	打印结果:
	第一次打印starting helloWorldGenerator()
    第二次打印starting helloWorldGenerator()
    第三次打印starting helloWorldGenerator()*/

Yield expression
Since the traverser object returned by the Generator function can traverse the next internal state only by calling the next method, it actually provides a function that can suspend execution. The yield expression is the pause sign.

The running logic of the next method of the iterator object is as follows.

(1) When a yield expression is encountered, the execution of the following operations is suspended, and the value of the expression immediately following the yield is used as the value attribute of the returned object.

(2) The next time the next method is called, the execution will continue until the next yield expression is encountered.

(3) If no new yield expression is encountered, it will run until the end of the function until the return statement, and use the value of the expression following the return statement as the value attribute of the returned object.

(4) If the function does not have a return statement (if there is no return at the end of the function, it is implicit return undefined;), the value attribute of the returned object is undefined.

    1function *helloWorldGenerator(){
    
    
    console.log('第一次打印starting helloWorldGenerator()');
    yield 123+456;
   }
	let res=helloWorldGenerator();
	res.next();
	let result=res.next();
	console.log('value',result.value);  //值为undefined,原因没有retrun语句
   2function *helloWorldGenerator(){
    
    
    console.log('第一次打印starting helloWorldGenerator()');
    yield;
    yield 123+456;
    return 123+456
	}
	let res=helloWorldGenerator();
	res.next();
	let result=res.next();
	console.log('value',result.value);  //value 579

Requests implemented using generators

function getCallSettings({
    
    url:"",type:"get",dataType:"json"}) {
    
    
     return new Promise((resolve,reject)=>{
    
    
        let xhr=new XMLHttpRequest();
        xhr.open(type,url,true);
        //后台给返回的数据类型,一般都是json
        xhr.responseType=dataType;
        xhr.onload=function(){
    
    
            if(xhr.code ==200 && xhr.readyState ==4){
    
    
                //成功调用
                resolve(res=>{
    
    
                   it.next(res.dialerSetting); // 将res.dialerSetting传给yield表达式
                });
            }
        }
        xhr.onerror=function(err){
    
    
            //失败调用
            reject(err=>{
    
    
                  it.throw(err); // 抛出错误
             })
        }
        xhr.send();
}
function *dealData() {
    
    
    try{
    
    
       let settingInfo = yield getCallSettings();
       //to do something……
    }
    catch(err) {
    
    
      console.log(err); // 捕捉错误
    }
}
let it = dealData();
it.next(); // 第一次调用next()是启动生成器

4. ES7's async and await
async functions improve the Generator function, which is reflected in the following four points
(1) Built-in actuator. The generator needs to call next() for the first time to start execution
(2) better semantics. Async and await have clearer semantics than asterisk and yield. async indicates that there are asynchronous operations in the function, and await indicates that the following expression needs to wait for the result
(3) wider applicability. The co module agrees that the yield command can only be followed by the Thunk function or the Promise object, while the await command of the async function can be followed by the Promise object and the value of the primitive type (numerical value, string and Boolean value, but it will be automatically converted to immediate resolved Promise object).
(4) The return value is Promise. The return value of the async function is a Promise object, which is much more convenient than the return value of the Generator function which is an Iterator object. You can use the then method to specify the next operation.
Multiple declaration forms of async

// 函数声明
async function foo() {
    
    }
// 函数表达式
const foo = async function () {
    
    };
// 对象的方法
let obj = {
    
     async foo() {
    
    } };
obj.foo().then(...)

The async function returns a promise. The value returned by the return statement inside the async function will become the parameter of the then method callback function.

async function f() {
    
    
  return 'hello world';
}
f().then(v => console.log(v))
// "hello world"

Under normal circumstances, the await command is followed by a Promise object, and the result of the object is returned. If it is not a Promise object, the corresponding value is returned directly.

async function f() {
    
    
  // 等同于
  // return 123;
  return await 123;
}
f().then(v => console.log(v))
// 123

In async, the await fun() is executed first, and the result is assigned to the left n after the execution is completed after three seconds. That is to say, the test function takes three seconds to complete the execution, so the test function is asynchronous, so the front must Write async, as follows

    function fun(){
    
    
        return new Promise((resolve, reject)=>{
    
    
            let sino = parseInt(Math.random() * 6 +1)
            setTimeout(()=>{
    
    
                resolve(sino)
            },2000)
        })
    }
    async function test(){
    
    
        let n =await fun()
        console.log('n',n)
    }

Guess you like

Origin blog.csdn.net/weixin_46918658/article/details/105531025