The callback function

Publish and subscribe model

Promise

Some of the features

  1. A Promise is a class that, when executed, passes in an executor that executes immediately;
  2. Promise can have three states
  • Pending on
  • Fulfilled complete
  • The rejected failure
  1. The status can only be fulfilled by pending -> depressing or pending -> Rejected, and once it changes, it cannot be modified again.
  2. Resolve and reject are used in Promise to change the state;
  3. What the then method does internally is make state judgments
  • If the status is success, the success callback is called
  • If the state is failure, the failure callback is called

Promise solves the nested callback problem

  • Promise implements delayed binding of callback functions
  1. Create the Promise object P
  2. The business logic is executed through the Promise constructor
  3. Once the Promise object P is created, the callback function is set up using P.teng
  • The return value of the callback function passes through to the external test

Promise handling exceptions

Promises and microtasks

  1. New A Promise class that passes in a function executor
  2. Execute the function executor
  3. If executor succeeds, call the resolve method
  4. The callback provided by the THEN method is called within the resolve method

In JavaScript, the code is executed from top to bottom. If the then method is not executed, then the callback function is not executed. In this case, the resolve method needs to delay the call of the callback function.

QueueMicrotask implements microtasks

Many handwritten versions have setTimeOut to do asynchronous processing, but setTimeOut belongs to macro task, which contradicts the Promise as a microtask, so we need to choose a way to create a microtask to achieve it.

NextTick (Node side) and MutationObserver (browser side). Considering the environmental judgment required to use these two methods, Therefore, using queueMicrotask to create microtasks is recommended.

Native calls

const promise = new Promise((resolve, reject) = > {
    resolve( 'success' )
    reject ( 'err' )
})

promise.then( value= > {
    console.log( 'resolve', value)
}, reason= > {
    console.log( 'reject', reason)
})
Copy the code

Write a Promise

Version 1

function MyPromise(executor){
    var onResolve_ = null
    var onReject_ = null
    this.then = function(onResolve, onReject){
        onResolve_ = onResolve
    }
    function resolve(value){
        // Call the callback function asynchronously
        queueMicrotask(function(){
            onResolve_(value)
        })
    }
    executor(resolve, null)}Copy the code
var p = new MyPromise(function(resolve,reject){
    resolve(100)
})
p.then(function(value){
    console.log(value)
})
Copy the code

Version 2

Juejin. Cn/post / 695345…

The generator generator

Underlying Implementation Mechanism — Coroutine

V8 implements pause and resume of functions – coroutines

coroutines

  • Coroutines are a much lighter form of existence than threads
  • You can think of coroutines as tasks running on threads
  • Multiple coroutines can exist on a thread, but only one coroutine can be executed on a thread at a time
  • Thread execution is in kernel mode, controlled by the operating system
  • The execution of coroutines is in user mode and is completely controlled by programs
  • Coroutine switching is performed in user mode, while thread switching requires switching from user mode to kernel mode, where scheduling is performed
  • Coroutines are much lighter and more efficient than threads

Some of the features

  • The Generator function is a Generator that returns an iterator when executed;
  • This iterator is also a coroutine
  • This coroutine can be executed by calling the generator’s next() method
  • This coroutine can be paused with the yield keyword, surrendering control of the main thread
  • The coroutine can be terminated by the return keyword

async await

Implementation principle of Async Function

  • Async function is implemented with Promise + Generator
  • The generator controls program scheduling through coroutines
  • When performing asynchronous tasks in coroutines, encapsulated with promise the asynchronous tasks first, and if the asynchronous task is complete, the result will be put to detail task queue, and then through the yield up the main thread executive power, continue to implement the main thread js, the main thread js execution has been completed, will go to scan task queue, if there are tasks to take out the tasks to perform, Asynchronous programming is implemented synchronously by calling the iterator’s next(result) method and passing in the task execution result, transferring the main thread execution to the coroutine to continue execution and assigning result to the variable to the left of the yield expression
  • So after all async function is implemented by coroutine + microtask + browser event loop mechanism

Analyze a problem and understand the implementation principle of async

1)new PromiseThe function passed in prints promise start (2Execute the resolve method, which internally asynchronously calls the first then passed function, putting the then passed function into the microtask queue (3Execute asyncFun1(), create coroutine asyncFun1()4)new PromiseFunction asyncFun1 (5Execute asyncFun1 method, outputasyncStart (6)new PromiseThe function asyncFun2 is passedfunction asyncFun1(){
         new Promise((reslove, reject) = >{
             var result = asyncFun2()
             resolve(result)
         }).then(result= > {
             returnThe result})} (7Execute asyncFun2 method, outputasyncAwait1 (8AsyncFun2 completes, and the result is returnedundefined, asyncFun2PromiseThe resolve callback is put into the microtask queue, asyncFun2PromiseThen ()value= >{
         return value //value is the result of asyncFun2}) and passyieldRelinquish main thread execution authority (9) continue to execute the main thread JS. After the main thread JS is executed, scan the microtask queue (10Then1 promise the first THEN is also a promise, Promise then1. Promise then1 puts the function passed in by the second PROMISE THEN into the microtask as a callback (11) finds the second task in the microtask queue, i.eawaitAsyncFun2 callback function (12) performawaitCallback function of asyncFun2 that passes the result back to coroutine asyncFun1 and resumes the execution of coroutine asyncFun1 (13Run)awaitAsyncFun3 () this line of code (14)new PromiseThe incoming asyncFun3 (15Execute asyncFun3 method, outputasync await2
        asyncFun3 PromiseThe resolve callback is put into the microtask and then relinquish execution authority to the main thread.16) continue to execute main-thread JS, after main-thread JS is executed, scan the microtask queue and find the callback function of the first task promise then1, then execute, enter Promise then2 and find the second taskasync await2
  
Copy the code
The title
async function asyncFun1(){  
   console.log('async start'); 
   await asyncFun2()
   await asyncFun3()
   console.log('async end')}async function  asyncFun2(){ 
    console.log('async await1');  
}

async function asyncFun3(){ 
    console.log('async await2')}new Promise((reslove) = >{ 
    console.log('promise start') 
    reslove() 
}).then(() = >{
    console.log('promise then1')
}).then(() = >{
    console.log('promise then2')
}).then(() = >{
    console.log('promise then3')
})

asyncFun1()  

Copy the code

The output is:

promise start
async start
async await1
promise then1
async await2
promise then2
async end
promise then3
Copy the code

Async (async) {async (promise) {async (promise) {async (promise) {async (promise) {async (promise) {async (promise) {async (promise);

Underlying implementation of async/await

The cryptography behind async/await technology is the application of promises and generators, and the underlying application of microtasks and coroutines.

async function foo() { 
    console.log(1)  // the second output
    let a = await 100 
    console.log(a) 
    console.log(2)}console.log(0) // first output
foo() // Start the foo coroutine
console.log(3)
Copy the code

When execution to await 100, a Promise object is created by default. The code is shown below

let p = new Promise((resolve, reject) = > {
    resolve(100)})Copy the code