Asynchronous and synchronous in JavaScript, callback function, promise, async and await

Ruffians and ruffians 2020-11-09 10:50:41
asynchronous synchronous javascript callback function


One 、 Asynchronous and synchronous

Understand asynchronous and synchronous

1、 In the life , To understand in terms of words , Asynchronous means , For example, I eat the apple first and then watch TV , This is the asynchrony of understanding in our lives . Synchronization means I watch TV while eating apples .

2、 However , For our computer programs , The concept of synchronization and asynchrony is exactly the opposite of what we understand in life . Synchronization means I eat the apple first , And then watch TV ( Execute one event before executing another , If the last event is not finished , The next event cannot be executed ); Asynchronous means I watch TV while eating apples ( Multiple events can be executed simultaneously , There will be no blockage ). understand js Asynchronous and synchronous in , If the two concepts are confused , You just have to think about the opposite of our understanding of asynchrony and synchrony in our lives .

Talk about JavaScript Single thread mechanism of (event loop?)

1、 Single thread yes JavaScript One of the more important features in .JS The main running environment is our client ( browser ), therefore , The single thread mechanism is more appropriate . such as , hypothesis JS It's multi-threaded , A thread adds a DOM node , Another thread deleted this node , At this time, the browser doesn't know which thread to use , It's too confusing .

2、 Single thread means that the event can only be one One by one , It's impossible to execute after the front has not been executed ( Just wait and wait , It's too inefficient ). such as , I use ajax Request a data from the server ( Suppose there's a lot of data , It takes a long time ), And then it gets stuck there , Because the latter can only wait for the previous event to successfully request data back to execute the next code , This is too unfriendly for the user experience . Now Task queue It's coming out .JS Divide all tasks into Synchronization task and Asynchronous task .

3、 At present, my personal understanding is , Only when all synchronous tasks are completed can asynchronous tasks be executed . Common asynchronous events are setTimeout function ,http request , Database query .

(1) All tasks are performed on the main thread , Form an execution stack (execution context stack).
(2) Outside the main thread , There is also a " Task queue "(task queue). The system places asynchronous tasks in " Task force Column " In , And then go on with the follow-up tasks .
(3) once " Execution stack "( Event loop queue ) All tasks in completion of enforcement , The system will read " Task queue ". If this time , The asynchronous task has finished waiting state , It will start from " Task queue " Enter the execution stack , Resume execution .
(4) The main thread repeats step 3 above .

See this article for details

 console.log(' Here's debugging 1');
setTimeout(() => {
console.log(' Here's debugging 2');
},0)
console.log(' Here's debugging 3');
console.log(' Here's debugging 4');
console.log(' Here's debugging 5');
// Output
Here's debugging 1
Here's debugging 3
Here's debugging 4
Here's debugging 5
Here's debugging 2 // setTimeout It's the last face of the game 

Choose asynchronous or synchronous ?

1、 stay JS The default mode in is synchronous , Individual is asynchronous (http request ,setTimeout). But now there's a scene , There is a front page , The client initiates a http request , Now the situation is , Only the request returns data successfully ( Allow rendering ), To show the content of the page to the user . Here, if we take the traditional way , because http The request belongs to an asynchronous task , Only when all tasks of the main thread are completed can we get http Data returned by request . This is contrary to the needs of our scenario . In order to meet the needs of our scenario , We have to make asynchronous tasks (http request ) Switch to synchronization task ( Get http The requested data then executes other events of the main thread )

2、 Common processing asynchrony ( Change asynchronous to synchronous ) According to the time of appearance, there are : Callback function ,Promise,async And await.

Two 、 Closures and callbacks

1、 By whatever means will Internal function Passed to this function definition Lexical scope ( The lexical scope of definition refers to the position where the function is defined ) outside perform , Internal functions hold references to the original defined scope , Closures are used wherever this function is executed .
2、 No matter where the function is called , And no matter how it's called , Its lexical scope is determined only by where the function is declared .
3、 Closures allow functions to continue to access lexical scopes at definition time .
4、 Just use the callback function , It's actually using closures .
---《 You don't know JavaScript》

1、 Generally speaking ,block( Block level ) After the scope is executed , The data is recycled .

2、 effect : The variables in a block level scope can be used externally .

3、 Lexical scope : Static scope , The order in which scopes are found is determined by the location of the function when it is defined .

4、 The global scope is in V8 It's created during startup , And it has been kept in memory and will not be destroyed , until V8 sign out . The function scope is created when the function is executed , When the function is finished , The function scope is destroyed .

Let's look at a closure case :

function foo() {
    let a = 2;
    function bar() {
        console.log(a);
        a++;
    }
    return bar;
}
let baz = foo();
baz(); // 2
baz(); // 3

function foo(...) Returns a file named bar Function of , next let baz = foo(); will bar(...) This function is assigned to baz, So to a certain extent baz amount to bar(...), And then we execute baz( stay bar Implemented outside the lexical scope of the definition )( Lexical scope : Where functions are defined , His lexical scope is just there ); This confirms what we said earlier , Pass an internal function to be executed outside the lexical scope of the function , So there's closure , Because we got it out there foo Variables within a function a, At the same time, it's also the effect of closures .

3、 summary :

  • When do closures occur : Pass a function to be executed outside the lexical scope of the function ;
  • The function of closures : Reference to a variable in a block level scope ( Keep quoting )

4、 Just use the callback function , It's actually using closures . Let's take a case study .

function wait(message) {
   setTimeout(function timer() {
     console.log(message);
   }, 1000);
}
wait('Hello, World');

Put an internal function ( be known as timer) Pass to setTimeout(...).timer Has coverage wait(...) Closure of scope , So we keep variables message References to .wait(...) perform 1000 Milliseconds later , Its internal scope doesn't disappear ,timer Functions still hold wait(...) Closure of scope . Because it can refer to message This variable .

5、 Let's look at a slightly more complicated case ( Use callback function to transfer value synchronously ):

//  Simulation acquisition ajax Requested data ( asynchronous )
function getAjaxData(cb) {
    //  use setTimeout Implementing asynchronous requests
    setTimeout(function() {
      //  hypothesis data It's the data we asked for   We need to send data to other people
      const data = " Requested data ";
      cb(data);
    }, 1000)
}
//  obtain ajax Request response data and process the data
getAjaxData(function handleData(tempData) {
    tempData = tempData + '666';
    console.log(tempData); // Requested data 666
});

take handleData(...) Pass in as a parameter getAjaxData(...) in , therefore cb(data) Medium data It's passed in as a parameter handleData(...) in , In this way, the value transfer function is achieved .

6、 The problem with callback function : The question of trust . Take the example above to improve .

function getAjaxData (cb) {
  //  use setTimeout Implementing asynchronous requests
  setTimeout(function () {
    //  hypothesis data It's the data we asked for   We need to send data to other people
    const data = " Requested data ";
    cb(data);
    cb(data);
  }, 1000)
}
//  obtain ajax Request response data and process the data
getAjaxData(function handleData (tempData) {
  tempData = tempData + '666';
  console.log(tempData); //  Requested data 666
});

hypothesis getAjaxData(...) This method was introduced from a third-party library , We don't know the logical details of the code , In this case handleData(...) There is uncertainty in the implementation of , For example, I added a cb(data), this handleData(...) It will be executed twice , Of course, this is not the effect we want , So the callback processing is out of control .

The biggest problem with callbacks is inversion of control , It can lead to a complete breakdown of the chain of trust .
Because the call situation inside the callback function is uncertain , May not call , It may have been called many times .
---《 You don't know JavaScript》

Promise It is to solve this problem .

7、 remarks : About js The problem of reclaiming memory in

3、 ... and 、Promise

Promise characteristic ( Relative callback function ):

  • Promise Once it's decided , The outcome of its decision remains unchanged
  • Solve the problem of premature callback calls
  • Solve the problem of calling callback too late
  • Solve the problem that the callback is not called
  • Solve the problem of too few or too many calls

Promise API summary

1、new Promise(...) Constructors

2、Promise.resolve(...) and Promise.reject(...)

3、then(...) and catch(...)

4、Promise.all([...]) and Promise.race([...])

Promise Source code interpretation

1、new Promise when , Need to pass on a executor actuator , The actuator executes immediately ;

2、executor Take two parameters , Namely resolve and reject;

3、promise Only from pending To rejected, Or from pending To fulfilled;

4、promise Once the status of is confirmed , It won't change ;

5、promise There are then Method ,then Take two parameters , Namely promise Successful callback onFulfilled, and promise Failed callback onRejected;

6、 If the then when ,promise Have succeeded , execute onFulfilled, And will promise The value of is passed in as an argument . If promise Have failed , Then perform onRejected, And will promise The reason for the failure is passed in as an argument . If promise The state of is pending, Need to put onFulfilled and onRejected Functions are stored , Wait for the status to be determined , Then execute the corresponding functions in turn ;

7、then Parameters of onFulfilled and onRejected You can default to ;

8、promise Sure then many times ,promise Of then Method returns a promise;

9、 If then What is returned is a result , Then this result will be taken as a parameter , Pass to next then A successful callback of (onFulfilled);

10、 If then Exception thrown in , Then this exception will be taken as a parameter , Pass to next then The failed callback of (onRejected);

11、 If then Back to a promise, Then we'll wait for this promise After execution ,promise If it works , Just go to the next one then The success of the , If you fail , Just go to the next one then The failure of the ;

technological process

1、 When promise There are asynchronous tasks in : If promise If there are asynchronous tasks in , What about his status by pedding, After that all then Will be put in the to-do list .
2、 Implementation of chain call :then Method returns a promise.
3、 When then There are asynchronous tasks in : Two cases :

  • It's just an asynchronous task : According to the normal situation , It will output at the end of .
  • Return to one promise: Asynchronous task in promise And there are resolve: Everything in the back then Will be placed in the to-do list , We have to wait until resolve(...) After that, the state will be changed before the execution of the following ( Traversing the to-do list ).

The source code to achieve & analysis

1、 Realization promise(...) Method , This method has a callback function exectue Parameters ;

When we new promise((resolve, reject) => {}); when , The callback function will be executed ;

also resolve Corresponding to promise(...) Medium res(...) ;

reject Corresponding to promise(...) Medium rej(...);

When we reach resolve(...) when , Will execute res(...);

function promise(exectue) {
  const res = (value) => { }
  const rej = (reason) => { }
  exectue(res, rej);
}
// resolve The corresponding is promise(...) Medium res(...)
// reject The corresponding is promise(...) Medium rej(...)
// So it's just execution resolve(...) or reject(...) To change status Value
const test = new promise((resolve, reject) => {
  console.log(' Here's debugging 1');
  setTimeout(() => {
    console.log(' Here's debugging 2');
    resolve();
  }, 3000)
})
// Here's debugging 1
// Here's debugging 2
// Yes res

2、promise(...) Method to maintain several variables , Used to store Execution node The state of & data :

  • fulfilled: Indicates whether the task is completed ;
  • pedding: Indicates whether the task is in progress ( Unfinished status );
  • status: Indicates the status of the current execution node , The initial state of the node is pedding;
  • value: Storage promise The value when the status is successful ;
  • reason: Storage promise The value when the state fails ;
  • onFulfilledCallbacks : Array , Store successful callback tasks ;
  • onRejectedCallbacks: Array , Store failed callback tasks ;
function promise(exectue) {
  this.fulfilled = 'fulfilled';
  this.pedding = 'pedding';
  this.rejected = 'rejected';
  this.status = this.pedding;
  this.value;
  this.reason;
  this.onFulfilledCallbacks = [];
  this.onRejectedCallbacks = [];
  const res = (value) => {
    if(this.status === this.pedding) {
      //  Yes resolve It's about to change status by fulfilled
      this.status = this.fulfilled;
      this.value = value;
      //  Traverse the execution of events placed in the to-do task array
      this.onFulfilledCallbacks.forEach(fn => fn());
    }
  }
  const rej = (reason) => {
    if(this.status === this.pedding) {
      //  Yes reject It's about to change status by rejected
      this.status = this.rejected;
      this.reason = reason;
      this.onRejectedCallbacks.forEach(fn => fn());
    }
  }
  exectue(res, rej);
}

3、 Realization then(...), To conform to the chain call ,then(...) Method must return a promise(...)

promise.prototype.then = function (onFulfilled, onRejected) {
// this Point to promise(...) object
  const that = this;
  const promise2 = new promise((resolve, reject) => {
    if(that.status === that.fulfilled) {
      onFulfilled();
resolve();
    }
    if(that.status === that.pedding) { }
    if(that.status === that.rejected) { }
  })
  return promise2;
}
// call
const test = new promise((resolve, reject) => {
  console.log(' Here's debugging 1');
  resolve();
})
test.then(() => {
  console.log(' Here's debugging 2');
}).then(() => {
  console.log(' Here's debugging 3');
})
// Here's debugging 1
// Here's debugging 2
// Here's debugging 3

4、 Come here , We have implemented the basic chain call function , Well, if it's in promise(...) When is an asynchronous event , And we need to block this asynchronous task ( Convert asynchrony to synchronization ), The expected effect is that only execution resolve(...) To perform then(...) The code in , How can it be done ?

When promise(...) When an asynchronous task needs to be blocked , Then when the then(...) when , At this time status by pedding, The execution node of the chain call needs to be set according to Fulfilled or Rejected Two cases are added to onFulfilledCallbacks or onRejectedCallbacks Of these two variables , Wait until the asynchronous task is finished ,resolve(...) Then it's the execution of the chain call node , Improve the code :

promise.prototype.then = function (onFulfilled, onRejected) {
  // this Point to promise(...) object
  const that = this;
  const promise2 = new promise((resolve, reject) => {
    if(that.status === that.fulfilled) {
      onFulfilled();
      resolve();
    }
    if(that.status === that.pedding) {
      console.log(' Here's debugging 4');
      this.onFulfilledCallbacks.push(() => {
        onFulfilled();
        resolve();
      })
    }
    if(that.status === that.rejected) {
      this.onRejectedCallbacks.push(() => {
        onRejected();
        reject();
      })
    }
  })
  return promise2;
}
// call
const test = new promise((resolve, reject) => {
  setTimeout(() => {
    console.log(' Here's debugging 1');
    resolve();
  }, 1000)
})
test.then(() => {
  console.log(' Here's debugging 2');
}).then(() => {
  console.log(' Here's debugging 3');
})
// Here's debugging 4
// Here's debugging 4
// Here's debugging 1
// Here's debugging 2
// Here's debugging 3

5、 Next , Here's another scene , When we're in then(...) There are asynchronous tasks in the method , We also want to block the asynchronous task , And how to do it ? According to the logic above, we can't block then(...) Method of the asynchronous task , You can try .

const test = new promise((resolve, reject) => {
  setTimeout(() => {
    console.log(' Here's debugging 1');
    resolve();
  }, 1000)
})
test.then(() => {
  setTimeout(() => {
    console.log(' Here's debugging 2');
  }, 2000)
}).then(() => {
  console.log(' Here's debugging 3');
})
// Output
// Here's debugging 4
// Here's debugging 4
// Here's debugging 1
// Here's debugging 3
// Here's debugging 2

If you want to block then(...) Asynchronous tasks in , There are two cases to discuss : One is to block asynchronous tasks , Need to be in then(...) Return to one promise(...), The other is that there is no need to block asynchronous tasks , Then you don't need to return any values . Continue to improve the code :

promise.prototype.then = function (onFulfilled, onRejected) {
  // this Point to promise(...) object
  const that = this;
  const promise2 = new promise((resolve, reject) => {
    if(that.status === that.fulfilled) {
        let x = onFulfilled(that.value); 
        if(x && typeof x === 'object' || typeof x === 'function') {
          let then = x.then;
          if(then) {
            then.call(x, resolve, reject);
          } else {
resolve(x);
}
    }
    if(that.status === that.pedding) {
      this.onFulfilledCallbacks.push(() => {
        // onFulfilled(...)  by then(...) Callback function in method
        let x = onFulfilled(that.value); //  Yes then(...) Method and assign the return value to x
        //  Judge then(...) The return value type of callback function in   Is it function
        if(x && typeof x === 'object' || typeof x === 'function') {
          let then = x.then;
          //  If then There is   Description returns a promise
          if(then) {
            //  The method used here is to resolve Put it back on the return promise Of then It's executed inside  .
            //  This is only when then(...) The asynchronous event in the method is executed resolve(...)  It's very boastful
// call(...) binding this The direction of
            then.call(x, resolve, reject);
          }
        } else {
          resolve(x);
        }
      })
    }
    if(that.status === that.rejected) {
      this.onRejectedCallbacks.push(() => {  
let x = onRejected(that.reason);
        if(x && typeof x === 'object' || typeof x === 'function') {
          let then = x.then;
          if(then) {
            then.call(x, resolve, reject);
          } else {
resolve(x);
}
      })
    }
  })
  return promise2;
}
const test = new promise((resolve, reject) => {
  setTimeout(() => {
    console.log(' Here's debugging 1');
    resolve();
  }, 1000)
})
test.then(() => {
  //  If you want to block then(...) Asynchronous tasks in need of return One promise
  return new promise((resolve1, reject1) => {
    setTimeout(() => {
      console.log(' Here's debugging 2');
      resolve1();
    }, 2000)
  })
}).then(() => {
  console.log(' Here's debugging 3');
})
// Here's debugging 1
// Here's debugging 2
// Here's debugging 3

6、 Come here , About promise The core content has basically been realized , Let's take a look at the following cases :

new promise(function(resolve){
    console.log(' Here's debugging 1');
    resolve();
}).then(function(){
    console.log(' Here's debugging 2');
});
console.log(' Here's debugging 3');
// Here's debugging 1
// Here's debugging 2
// Here's debugging 3
new Promise(function(resolve){
    console.log(' Here's debugging 1');
    resolve();
}).then(function(){
    console.log(' Here's debugging 2');
});
console.log(' Here's debugging 3');
// Here's debugging 1
// Here's debugging 3
// Here's debugging 2

You can find , our promise And the original Promise The output is different . according to Promise standard , stay .then(...) Method belongs to Micro task ( Asynchronous tasks are divided into Micro task and Macro task , General asynchronous events are macro tasks , Micro tasks execute before macro tasks , But we did it ourselves promise This rule is not supported , Native Promise To support ), So you need to turn it into an asynchronous task , Now let's use setTimeout(...) To simulate the implementation of asynchronous tasks ( Native Promise It's not for setTimeout(...) Realized )

promise.prototype.then = function (onFulfilled, onRejected) {
  const that = this;
  const promise2 = new promise((resolve, reject) => {
    if (that.status === that.fulfilled) {
      setTimeout(() => {
        let x = onFulfilled(that.value);
        if (x && typeof x === 'object' || typeof x === 'function') {
          let then = x.then;
          if (then) {
            then.call(x, resolve, reject);
          }
        } else {
          resolve(x);
        }
      })
    }
    if (that.status === that.pedding) {
      that.onFulfilledCallbacks.push(() => {
        setTimeout(() => {
          let x = onFulfilled(that.value);
          if (x && typeof x === 'object' || typeof x === 'function') {
            let then = x.then;
            if (then) {
              then.call(x, resolve, reject);
            }
          } else {
            resolve(x);
          }
        })
      })
      that.onRejectedCallbacks.push(() => {
        setTimeout(() => {
          let x = onRejected(that.reason);
          if (x && typeof x === 'object' || typeof x === 'function') {
            let then = x.then;
            if (then) {
              then.call(x, resolve, reject);
            }
          } else {
            resolve(x);
          }
        })
      })
    }
    if (that.status === that.rejected) {
      setTimeout(() => {
        let x = onRejected(that.reason);
        if (x && typeof x === 'object' || typeof x === 'function') {
          let then = x.then;
          if (then) {
            then.call(x, resolve, reject);
          }
        } else {
          resolve(x);
        }
      })
    }
  })
  return promise2;
}
// Here's debugging 1
// Here's debugging 3
// Here's debugging 2

7、 Let's take another example :

const test = new promise((res, rej) => {
  setTimeout(() => {
    console.log(' Here's debugging 1');
    res();
  }, 4000);
})
//  Callback function push Into the test.onFulfilledCallbacks Array
test.then(() => {
  return new promise((res1) => {
    setTimeout(() => {
      console.log(' Here's debugging 2');
      res1();
    }, 3000);
  })
})
//  The callback function is also push Into the test.onFulfilledCallbacks Array , So two then(...) It's independent of each other , The execution order is dealt with in the normal way
test.then(() => {
  console.log(' Here's debugging 3');
})
// Output
// Here's debugging 1
// Here's debugging 3
// Here's debugging 2

Source code implementation reference
Macro task micro task reference

Four 、async And await

  • async、await be relative to promise More waiting effects ;
  • principle : Promise + generator = async/await;
  • async Function must return a Promise object . If one async The return value of the function does not appear to be promise, Then it will be implicitly packaged in a promise in ;
  • important : Use async And await when ,await The following function must return the resolution of Promise, Otherwise , The program will stop at await This step ;
  • async、await Relative to promise More waiting effects ; How to realize it ?--- Used yield Pause function , Only waiting for the front promise Only after the resolution is implemented next(...), The program continues to run later , What it shows is the effect of suspending the program ;

iterator

1、 A special object , Proprietary interfaces designed for iterative processes , In short, it's similar to traversing an object ;

2、 Call returns a result object , Among objects next() Method ;

3、next() Method returns an object : value: Represents the next value to return ;done: When there is no value to return true, Otherwise false;

4、 Iterators are easy to implement internally :

function createIterator(items) {
  let i = 0;
  return {
    next: function() {
      let done = (i >= items.length);
      // items[i++]  amount to  items[i]; i++;
      let value = !done ? items[i++] : undefined;
      return {
        value: value,
        done: done // true It means that there is no value after
      };
    }
  };
}
//  Only one instance has been created   therefore iterator It's always the same
let iterator = createIterator([1,2,3]);
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

generator

1、 A return iterator Function of ; It implements a sequence 、 Seemingly synchronous asynchronous process control expression style ;
2、 keyword yield: Indicates that the function is suspended ;
3、 The process : Every time I finish one yield The function pauses after the statement , Until you call the function again next() Method will continue to execute the following statement ;
4、 Use yield Keyword can return any value or expression ( Represents the value to be passed to the next procedure );
5、 Be careful :

  • yield Keywords can only be used directly inside the generator function ( If used in the function inside the generator function, an error will be reported );
  • You can't use arrow functions to create generators ;

Easy to use example :

function *createInterator() {
  yield 1;
  yield 2;
  yield 3;
}
//  The generator is called in the same way as a normal function , It just returns an iterator
let iterator = createInterator();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

Iterative messaging :

function *foo(x) {
  const y = x * (yield);
  return y;
}
const it = foo(6);
//  start-up foo(...)
it.next(); 
const res = it.next(7); // next(...) The quantity of is always more than yield One more
console.log(res); // 42

First , Pass in 6 As a parameter . And then call it.next(...), This will activate *foo(...);

next , stay *foo(...) Inside , Start statement execution const y = x ..., But then there was one yield expression . It will be at this point Pause *foo(...)( In the middle of the assignment statement ), It's not essential that the calling code be yield The expression provides a result value . Next , call it.next(7), This sentence is worth 7 Return as suspended yield Expression result .

therefore , This is an assignment statement, which is actually const y = 6 * 7. Now? ,return y Return value 42 As a call it.next(7) Result .

Be careful , Depending on your perspective ,yield and next(...) Call has a mismatch . Generally speaking , Needed next(...) Calling is more than yield One more sentence , The previous code snippet has one yield And two next(...) call .

Because the first one next(...) Always used to start the generator , And run to the first yield It's about . however , It's the second one. next(...) Call to complete the first suspended yield expression , Third next(...) Finish the second one yield, And so on .

The message is two-way :

yield(...) As an expression , You can send a message response next(...);

next(...) You can also turn to the suspended yield Expressions send values . Be careful : We said earlier , first next(...) It's always used to start the generator , There is no pause at this time yield To accept such a value , Both the specification and the browser will drop and pass to the first one by default next(...) Anything of . therefore , Start the generator with no parameters next(...);

function *foo(x) {
  const y = x * (yield "Hello");
  return y;
}
const it = foo(6);
let res = it.next(); // first next(), It doesn't introduce anything
console.log(res.value); // Hello
res = it.next(7); // To wait for yield Pass in 7
console.log(res.value); // 42

The source code to achieve & analysis

async&await It's based on generators +Promise Encapsulated grammar sugar , Use async Embellished function It will actually be converted into a generator function , And return to a resolution of Promise(...),await The corresponding is yield, therefore await Only by async Used in decorated methods

Here's an example : This is a common use of async/await The case of

//  Simulate multiple asynchronous situations
function foo1() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(100); //  If there is no resolution (resolve) You don't run the next one
    }, 3000)
  })
}
function foo2() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(200);
    }, 2500)
  })
}
async function test() {
  const f1 = await foo1();
  const f2 = await foo2();
  console.log(' Here's debugging 1');
  console.log(f1);
  console.log(f2);
  return 'haha';
}
test().then((data) => {
  console.log(' Here's debugging 2');
  console.log(data);
});
// Here's debugging 1
// 100
// 200
// Here's debugging 2
// haha

Then let's take a look at how to use the async/await use generator +Promise To achieve :

take test(...) Convert to generator function :

function *test() {
  const f1 = yield foo1();
  const f2 = yield foo2();
  console.log(' Here's debugging 1');
  console.log(f1);
  console.log(f2);
  return 'haha';
}

Implementation method run(...), Used to call the generator *test(...)

function run(generatorFunc) {
  return function() {
    const gen = generatorFunc();
// async Default return Promise
    return new Promise((resolve, reject) => {
      function step(key, arg) {
        let generatorResult;
        try {
// Equivalent to execution gen.next(...)
          generatorResult = gen[key](arg);
        } catch (error) {
          return reject(error);
        }
// gen.next() The result is a { value, done } Structure
        const { value, done } = generatorResult;
        if (done) {
          return resolve(value);
        } else {
          return Promise.resolve(value).then(val => step('next', val), err => step('throw', err));
        }
      }
      step("next");
    })
  }
}
const haha = run(test);
haha().then((data) => {
  console.log(' Here's debugging 2');
  console.log(data);
});
// Here's debugging 1
// 100
// 200
// Here's debugging 2
// haha
版权声明
本文为[Ruffians and ruffians]所创,转载请带上原文链接,感谢

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云