As you probably know, the Javascript language is executed in a “single thread” environment.

Single-threaded means that you can only complete one task at a time. If there are multiple tasks, they must be queued, the first task completed, the next task executed, and so on.

The advantage of this mode is that the implementation is relatively simple, the execution environment is relatively simple; The disadvantage is that as long as one task takes a long time, subsequent tasks must wait in line, which will delay the execution of the entire program. A common browser non-response (suspended animation) is usually the result of a single piece of Javascript code running for so long (such as an infinite loop) that the entire page gets stuck in one place and no other task can be performed.

To solve this problem, the Javascript language divides the execution mode of the task into two modes: Synchronous and Asynchronous.

1. The callback

Callbacks are the most basic approach to asynchronous programming.

Suppose you have two functions f1 and f2, the latter waiting for the result of the former.

f1();
f2();
Copy the code

If f1 is a time-consuming task, consider rewriting F1 to write f2 as a callback function of F1.

function f1(callback){setTimeout(function () {// the task code for f1The callback (); },1000);
}
Copy the code

The executing code looks like this

f1(f2);
Copy the code

In this way, we change the synchronous operation to asynchronous operation. F1 does not block the program execution, which is equivalent to executing the main logic of the program first and postponing the execution of time-consuming operation. The advantages of the callback function are that it is simple, easy to understand, and deploy. The disadvantages are that it is not easy to read and maintain the code, the parts are highly coupled, the process can be messy, and only one callback function can be specified per task.

2.Promise

Promises Objects are a specification developed by the CommonJS working group to provide a unified interface for asynchronous programming.

In a nutshell, the idea is that ** each asynchronous task returns a Promise object that has a THEN method that allows callback functions to be specified. Promises greatly improve async dilemma, avoid callback hell, and improve nested hierarchies.

Basic Api

Promise.resolve()
Promise.reject()
Promise.prototype.then()
Promise.prototype.catch()
Promise.all()  // All done
Promise.race() // Finish one
Copy the code

See Ruan yifong’s Introduction to ECMAScript 6 for a detailed introduction to the API

Simulate two asynchronous requests

The associated reject() and catch() methods for the Rejected state of the Promise are omitted for the sake of code introduction

  / / 1 request
  function getData1 () {
    return new Promise(function (resolve, reject) {
      setTimeout(() = > {
        console.log('1 executed ')
        resolve('Request to analog data 1111 pull')},2000)})}/ / 2 requests
  function getData2 (params) {
    return new Promise(function (resolve, reject) {
      setTimeout(() = > {
        console.log('2 executed ')
        resolve('Request to analog data 22222 pull! Params: ' + params)
      }, 1500)})}Copy the code

Promise implements asynchronous callback asynchronous queue

After request 1 completes, pass the response parameters of 1 to 2, and send request 2

  function promiseDemo () {
    getData1()
      .then(res= > {
        return getData2(res)
      })
      .then(res= > {
        console.log(res)
      })
  }
  promiseDemo()
  // 1 is executed
  // 2 Execute
  // Request to analog data 22222 pull! Params: Request to simulated data 1111 takes 3500 ms to pull
Copy the code

Promise.all () implements asynchronous callbacks concurrent with all completion

1 request and 2 request are sent at the same time. Execute the request after receiving both responses

  function promiseDemo () {
    Promise.all([getData1(), getData2()]).then(function (res) {
      console.log(res)
    })
  }
  // 2 Execute
  // 1 is executed
  Params: undefined"); // select 'id' from 'id'
Copy the code

Promise.race () implements asynchronous callback concurrent racing

Request 1 and request 2 are sent at the same time, and one of them is executed upon receiving the request

  function promiseDemo () {
    Promise.race([getData1(), getData2()]).then(function (res) {
      console.log(res)
    })
  }
  // 2 Execute
  // Request to analog data 22222 pull! Params: undefined at 1500 ms
  // 1 is executed
Copy the code

As a result, the Promise object works well, and the control over the asynchronous flow is greatly improved, with the.then() method making chaining calls. But using.then().catch() also makes the code very ugly and very nested, so async/await comes out

3.Async/await

Async /await is a new way for Javascript to write asynchronous programs. Past asynchronous methods have been nothing more than callback functions and promises. But async/await is built on Promise.

How do I use Async functions

Let’s take a look at nguyen Yifeng’s introduction to ECMAScript 6

async function timeout(ms) {
  await new Promise((resolve) = > {
    setTimeout(resolve, ms);
  });
}

async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}

asyncPrint('hello world'.50);
Copy the code

The code above specifies that after 50 milliseconds, it prints Hello World. Further, async functions can be thought of as multiple asynchronous operations wrapped as a Promise object, and await commands are syntactic sugar for internal THEN commands

Let’s look at a concrete example

Async implements asynchronous callback asynchronous queue

After request 1 completes, pass the response parameters of 1 to 2, and send request 2

The promise implementation method mentioned above is a chain call to THEN, but async is more concise

  async function asyncDemo () {
    const r1 = await getData1()
    const r2 = await getData2(r1)
    console.log(r2)
  }
  // 1 is executed
  // 2 Execute
  // Request to analog data 22222 pull! Params: Request to simulated data 1111 takes 3500 ms to pull
Copy the code

Asynchronous code is realized by synchronous writing. Wait for the asynchronous function getData1 to complete and send the return value to R1, pass it to R2, and execute R2

Async Asynchronous callback concurrency

1 request and 2 request are sent at the same time, specifying the arrival sequence of the request

Suppose we have a business requirement to make two requests, but specify the order in which they are received? Here or draw lessons from ruan a peak god of the code

  async function asyncDemo2 () {
    const arr = [getData1, getData2]
    const textPromises = arr.map(async function (doc) {
      const response = await doc()
      return response
    })
    // Output in order
    for (const textPromise of textPromises) {
      console.log(awaittextPromise); }}// 2 is executed first (because 2 is executed after 1500ms)
  // 1 is executed
  // Request to analog data 1 pull (for.. Of specifies the order of output
  // Request to analog data 22222 pull! Params: undefined
Copy the code

In the above code, although the map method takes an async function as an argument, it is executed concurrently, because only the async function is executed internally, and the outside is not affected. Behind the for… The of loop uses await inside, so it outputs sequentially

Async summary

It makes asynchronous code less obvious as well, but it is best to choose asynchronous programming that is appropriate for the situation. Async is the syntactic sugar for Generator functions. So take a look at Generator functions if you want to understand more