2021 Best JavaScript asynchronous programming guide

Best JavaScript asynchronous programming guide, js is single-threaded, and the execution stack and rendering thread of js in the browser block each other. The biggest advantage of single-threaded mode is that it is safer and simpler.

JavaScript asynchronous programming
JavaScript asynchronous programming

Advantages and disadvantages of single thread

js is single-threaded, and the execution stack and rendering thread of js in the browser block each other. JavaScript asynchronous programming.

The biggest advantage of single-threaded mode is that it is safer and simpler. The
disadvantage is also clear, that is, if there is a particularly time-consuming task in the middle, other tasks will have to wait a long time, resulting in suspended animation.

In order to solve this problem, js has two task execution modes: synchronous mode (Synchronous) and asynchronous mode (Asynchronous) .

JavaScript asynchronous programming

Synchronous mode

It means that the tasks of the code are executed in sequence, and the latter task must wait for the end of the previous task to start execution.

The execution sequence of the program and the writing sequence of the code are exactly the same.

In single-threaded mode, most tasks will be executed in synchronous mode. JavaScript asynchronous programming.

Disadvantages : Because it is similar to queued execution, if once a certain operation is particularly time-consuming, the page will freeze and freeze, so asynchronous mode is required.

Asynchronous mode

Asynchronous mode does not wait for the end of this task to start the next task. It executes the next task immediately after it is turned on. The subsequent logic of the time-consuming function will be defined in the form of a callback function . After the task is completed, the callback function is called.

Asynchronous mode is very important for single-threaded JavaScript. Without this mode, single-threaded JavaScript cannot handle a large number of time-consuming tasks at the same time.

The biggest difficulty in the asynchronous mode under single thread is the disorder of code execution.

JavaScript asynchronous programming
JavaScript asynchronous programming

The way the asynchronous code is executed is simply:

  1. The js thread initiates an asynchronous call at a certain moment, and then it continues to perform other tasks.
  2. At this time, the asynchronous thread will execute the asynchronous task separately, and will put the callback in the message queue after execution.
  3. After the js main thread executes the task, it will execute the tasks in the message queue in turn.

It should be emphasized here that js is single-threaded, and browsers are not single-threaded. There are some APIs that have separate threads to do. JavaScript asynchronous programming.

Callback

Callback function : a function defined by the caller and handed over to the executor for execution

// callback is the callback function
// The function is passed as a parameter. The disadvantage is that it is not conducive to reading and the execution order is chaotic.
function foo(callback) {
     setTimeout(function(){
         callback()
     }, 3000)
}

foo(function() {
     console.log('This is a callback function')
     console.log('The caller defines this function, and the executor executes this function')
     console.log('In fact, the caller tells the executor what to do after the asynchronous task ends')
})

JavaScript asynchronous programming

Promise asynchronous solution

Promise overview

The multiple nesting of callbacks will cause the code to be less readable, hard to write, and error-prone, so it is called callback hell.
To avoid this problem. The CommonJS community proposed the Promise specification, which is called the language specification in ES6.

Promise is an object used to express whether an asynchronous task succeeds or fails after execution. It has multiple states:

  1. Pending status, which means that it is not clear whether the result of asynchronous execution is success or failure.
  2. Fulfilled completed status, indicating that the operation has been completed
  3. Rejected operation failed
JavaScript asynchronous programming
JavaScript asynchronous programming

Basic usage of Promise

Return to resolve

const promise = new Promise((resolve, reject) => {
  resolve(100)
})

promise.then((value) => {
  console.log('resolved', value) // resolve 100
},(error) => {
  console.log('rejected', error)
})

JavaScript asynchronous programming

Return reject

const promise = new Promise((resolve, reject) => {
  reject(new Error('promise rejected'))
})

promise.then((value) => {
  console.log('resolved', value)
},(error) => {
  console.log('rejected', error)
})

JavaScript asynchronous programming

Even if there is no asynchronous operation in the promise, the callback function of the then method will still enter the event queue.

Promise chain call

The then method of the promise object returns a brand new promise object. You can continue to call the then method. If the return is not a promise object, but a value, then this value will be passed as the value of the resolve. If there is no value, the default is undefined.

The following then method is to register a callback for the Promise returned by the previous then.

The return value of the callback function in the previous then method will be used as the callback parameter of the subsequent then method.

If the promise is returned in the callback, then the callback of the then method will wait for its end.

// promise is assumed to be a Promise instance
// The callback in then returns a Promise instance
promise.then(()=>{
return new Promise((resolve,reject)=>{
// some code
resolve("actual parameter A")
})
}).then( (Receive the actual parameter A)=>{ as the callback in the previous then})


// The callback return in then is not a promise instance
promise.then(()=>{ return 123 })
.then(val=>{ console.log(val) // 123 })

JavaScript asynchronous programming

Promise exception handling

onRejected method of callback in then

Which is the second callback function in then

.catch() (recommended)

If the second callback is not passed in then then the exception will enter the callback processing of catch

If there is an exception in the promise, the reject method will be called, and you can also use .catch()

It is more common to use the .catch method because it is more in line with chain calls

The unhandledrejection event on the global object

You can also register an unhandledrejection event on the global object to handle promise exceptions that are not manually caught in the code. Of course, it is not recommended to use

// browser
window.addEventListener('unhandledrejection', event => {
   const {reason, promise} = event
   console.log(reason, promise)

   //reason => Promise failure reason, usually an error object
   //promise => Promise object with exception

   event.preventDefault()
}, false)

// node
process.on('unhandledRejection', (reason, promise) => {
   console.log(reason, promise)

   //reason => Promise failure reason, usually an error object
   //promise => Promise object with exception
})

JavaScript asynchronous programming

Two static methods

Promise.resolve

  1. Without parameters, return a Fulfilled state behind the Promise object. Then executes the first callback in then
  2. The parameter is a simple data type and returns a Fulfilled state behind the Promise object. Then executes the first callback in then, and passes the parameter as an actual parameter to the callback
  3. If the incoming is a Promise object, the Promise.resolve method returns as it is
  4. If you pass in an object with the same then method as Promise, Promise.resolve will execute this object as a Promise
Promise.resolve('foo')
   .then(function (value) {
     console.log(value)
   })

new Promise(function (resolve, reject) {
   resolve('foo')
})

// If the incoming is a Promise object, the Promise.resolve method returns as it is

var promise = ajax('/api/users.json')
var promise2 = Promise.resolve(promise)
console.log(promise === promise2)

// If you pass in an object with the same then method as Promise,
// Promise.resolve will execute this object as a Promise

Promise.resolve({
   then: function (onFulfilled, onRejected) {
     onFulfilled('foo')
   }
})
.then(function (value) {
   console.log(value)
})

JavaScript asynchronous programming

Promise.reject

The Promise.reject() method returns a Promise object with a reason for rejection

// Any value passed in Promise.reject will be used as the reason for the failure of this Promise

  Promise.reject(new Error('rejected'))
   .catch(function (error) {
      console.log(error)
    })

Promise.reject('anything')
   .catch(function (error) {
     console.log(error)
   })

JavaScript asynchronous programming

Promise parallel execution

.all()

The Promise.all method accepts an array as a parameter. The objects in the array (p1, p2, p3) are all promise instances (if it is not a promise, the item will be converted to a promise by Promise.resolve).

Return a brand new Promise instance whose state is determined by these three promise instances. Only when all of them are fulfilled, the new Promise will enter fulfilled.

.race()

The Promise.race method also accepts an array as a parameter. When the state of one of the instances of p1, p2, and p3 changes (becomes fulfilled or rejected), the state of p changes accordingly. And pass the return value of the first promise that changes state to the callback function of p

Promise execution timing

How to simply understand the macro tasks and micro tasks. For
example, if you queue up for business in the bank,

then everyone in the queue can be regarded as a macro task.

When the queue arrives, you tell the teller that you need to apply for a card, deposit money, and transfer money. These are microtasks. The teller will not let you re-queue after finishing a business, but handle all your micro tasks at once. Then it will be the next person’s turn, which is the next macro task.

Macro task

(macro) task, it can be understood that the code executed each time the stack is executed is a macro task (including each time an event callback is obtained from the event queue and placed on the execution stack).

The macro task includes

script (overall code, synchronous code)
setTimeout
setInterval
I/O
UI interaction events
postMessage
MessageChannel
setImmediate (Node.js environment)

JavaScript asynchronous programming

Micro task

(micro)task, it can be understood that it is a task that is executed immediately after the execution of the current task ends. In other words, after the current task, before the next task, before rendering.
Micro tasks include

Promise.then
Object.observe
MutaionObserver
process.nextTick (Node.js environment)

JavaScript asynchronous programming

Determine the result of code execution

// micro task

console.log('global start')

// The callback of setTimeout is a macro task, which enters the callback queue
setTimeout(() => {
   console.log('setTimeout')
}, 0)

// The callback of Promise is a micro task, which is executed directly at the end of the call
Promise.resolve()
   .then(() => {
     console.log('promise')
   })
   .then(() => {
     console.log('promise 2')
   })
   .then(() => {
     console.log('promise 3')
   })

console.log('global end')

JavaScript asynchronous programming

turn out:

// The synchronization code is regarded as a macro task. After the execution is completed, all micro tasks generated in the macro task stage are executed, that is, the then in the promise, and then the next macro task is executed
global start
global end
promise
promise 2
promise 3
setTimeout

JavaScript asynchronous programming

Generator asynchronous scheme, Async/Await syntax sugar

Generator generator function

The Generator function can pause execution and resume execution. In addition, it has two features: data exchange inside and outside the function body and error handling mechanism.
The next method does not pass parameters and returns an object. The next method passes in parameters and passes the parameters to the value attribute of the return value of the function. The generator function outputs data to the outside; the next method can also accept parameters, which are input into the generator function data.

function* gen(x){
  var y = yield x + 2;
  return y;
}

var g = gen(1);
g.next() // { value: 3, done: false }
g.next(2) // { value: 2, done: true }

JavaScript asynchronous programming

In the above code, the value attribute of the first next method returns the value of the expression x + 2 (3). The second next method takes parameter 2. This parameter can be passed to the Generator function, as the return result of the asynchronous task of the previous stage, and received by the variable y in the function body. Therefore, the value attribute of this step returns 2 (the value of variable y).

Error handling code can also be deployed inside the Generator function to capture errors thrown outside the function.

function* gen(x){
   try {
     var y = yield x + 2;
   } catch (e){
     console.log(e);
   }
   return y;
}

var g = gen(1);
g.next();
g.throw('Something went wrong');
// error

JavaScript asynchronous programming

In the last line of the above code, outside the Generator function, the error thrown by the throw method of the pointer object can be caught by the try…catch code block in the function body.

Generator cooperating with Promise’s asynchronous solution can use the co library in development.
Of course, “My lord, the times have changed”We now use async / await

Async/Await syntactic sugar

Everyone has used it a lot, so I won’t repeat it.

Basic usage

async function main () {
  try {
    const users = await ajax('/api/users.json')
    console.log(users)
    const posts = await ajax('/api/posts.json')
    console.log(posts)
    const urls = await ajax('/api/urls.json')
    console.log(urls)
  } catch (e) {
    console.log(e)
  }
}

JavaScript asynchronous programming

Exception handling

Let the Promise object behind await catch itself
You can also catch the Promise object returned by the outside async function uniformly
Like synchronization code, put it in a try…catch structure;

Leave a Comment