Asynchronous solutions promise and wait

Time:2021-11-27

preface

Asynchronous programming mode is becoming more and more important in the front-end development process. From the initial XHR to the encapsulated Ajax, they are trying to solve the problems in the process of asynchronous programming. With the advent of the new ES6 standard, there is a new scheme to deal with asynchronous data flow. We all know that in traditional Ajax requests, when the data between asynchronous requests are dependent, ugly multi-layer callbacks may occur, commonly known as’ callback Hell ‘, which is daunting,Promise lets us bid farewell to callback functions and write more elegant asynchronous code。 In practice, promise is not perfect. Async / wait is one of the most revolutionary features added to JavaScript in recent years,Async / await provides an alternative way to make asynchronous code look like synchronous code。 Next, we introduce these two schemes to deal with asynchronous programming.

1、 Promise’s principle and basic grammar

1. Principle of promise

Promise is a kind of encapsulation of asynchronous operations. You can add methods to execute when asynchronous operations succeed or fail through independent interfaces. The mainstream specification is promises / A +.

There are several states in promise:

  • Pending: initial state, not fully or rejected;
  • Fully: successful operation. For convenience of expression, resolved is used to replace fully;
  • Rejected: failed operation.

Pending can be converted to fully or rejected and can only be converted once, that is, if pending is converted to fully, it can no longer be converted to rejected. Moreover, the fully and rejected states can only be converted from pending, and they cannot be converted to each other.

2. Basic syntax of promise

  • Promise instance must implement then method
  • Then () must be able to take two functions as arguments
  • Then() must return a promise instance
//If the lower version browser does not support promise, use CDN in this way

function loadImg(src) {
  var promise = new Promise(function(resolve, reject) {
    var img = document.createElement('img')
    img.onload = function() {
      resolve(img)
    }
    img.onerror = function() {
      Reject ('picture loading failed ')
    }
    img.src = src
  })
  return promise
}
var src = 'https://www.imooc.com/static/img/index/logo_new.png'
var result = loadImg(src)
result.then(
    function(img) {
      console.log(1, img.width)
      return img
    },
    function() {
      console.log('error 1')
    }
  ).then(function(img) {
    console.log(2, img.height)
  })

2、 Promise multiple series operations

Promise can also do more things. For example, there are several asynchronous tasks. You need to do task 1 first. If it succeeds, then do task 2. If any task fails, you will not continue and execute the error handling function. To execute such asynchronous tasks serially without promise, you need to write nested code layer by layer.

With promise, we just need to write it simplyjob1.then(job2).then(job3).catch(handleError);
Where job1, job2 and job3 are promise objects.

For example, we want to load the second image after the first image is loaded. If one of them fails, execute the error function:

var src1 = 'https://www.imooc.com/static/img/index/logo_new.png'
Var result1 = loadimg (SRC1) // result1 is the promise object
var src2 = 'https://img1.mukewang.com/545862fe00017c2602200220-100-100.jpg'
Var result2 = loadimg (src2) // result2 is the promise object
result1.then(function (img1) {
  Console.log ('first picture loading completed ', img1. Width)
  Return result2 // chain operation
}).then(function (img2) {
  Console.log ('second picture loading completed ', img2. Width)
}).catch(function (ex) {
  console.log(ex)
})

Note here:The then method can be called multiple times by the same promise, and the then method must return a promise object。 In the above example, if result1.then does not return a promise instance in clear text, it defaults to its own promise instance, that is, result1. Then returns a result2 instance and executes it later. Then actually executes result2.then

3、 Promise common methods

In addition to executing several asynchronous tasks serially, promise can also execute asynchronous tasks in parallel

Imagine a page chat system. We need to obtain the user’s personal information and friend list from two different URLs. These two tasks can be performed in parallel. Promise. All() is implemented as follows:

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
//Execute P1 and P2 simultaneously and then:
Promise.all([p1, p2]).then(function (results) {
    console.log(results); //  Get an array: ['p1 ',' P2 ']
});

Sometimes, multiple asynchronous tasks are for fault tolerance. For example, to read the user’s personal information from two URLs at the same time, you only need to get the results returned first. In this case, promise. Race() is used to implement:

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
Promise.race([p1, p2]).then(function (result) {
    console.log(result); // 'P1'
});

Since P1 executes faster, promise’s then() will get the result ‘P1’. P2 is still executing, but the execution result will be discarded.

Summary: promise.all accepts an array of promise objects. After all are completed, execute success uniformly;

Promise.race accepts an array containing multiple promise objects, and executes success as long as one is completed

Next, let’s modify the above example to deepen our understanding of the two:

var src1 = 'https://www.imooc.com/static/img/index/logo_new.png'
var result1 = loadImg(src1)
var src2 = 'https://img1.mukewang.com/545862fe00017c2602200220-100-100.jpg'
var result2 = loadImg(src2)
Promise.all([result1, result2]).then(function(datas) {
  console.log('all', datas[0]) //
  console.log('all', datas[1]) //
})
Promise.race([result1, result2]).then(function(data) {
  console.log('race', data) //
})

If promise is used in combination, many asynchronous tasks can be executed in parallel and serial

4、 Introduction and usage of async / await

Asynchronous operation is a trouble in JavaScript programming. Many people think that async function is the ultimate solution to asynchronous operation.

1. Introduction to async / await

  • Async / await is a new way to write asynchronous code, which is better than callback functions and promise.
  • Async / await is implemented based on promise and cannot be used for ordinary callback functions.
  • Async / await, like promise, is non blocking.
  • Async / await makes asynchronous code look like synchronous code, and there are no callback functions. However, it can not change the single threaded and asynchronous nature of JS.

2. Usage of async / await

  • With await, functions must be identified with async
  • Await is followed by a promise instance
  • Babel Polyfill needs to be installed. Remember to introduce / / NPM I — save dev Babel Polyfill after installation
function loadImg(src) {
  const promise = new Promise(function(resolve, reject) {
    const img = document.createElement('img')
    img.onload = function() {
      resolve(img)
    }
    img.onerror = function() {
      Reject ('picture loading failed ')
    }
    img.src = src
  })
  return promise
}
const src1 = 'https://www.imooc.com/static/img/index/logo_new.png'
const src2 = 'https://img1.mukewang.com/545862fe00017c2602200220-100-100.jpg'
const load = async function() {
  const result1 = await loadImg(src1)
  console.log(result1)
  const result2 = await loadImg(src2)
  console.log(result2)
}
load()

When the function is executed, once await is encountered, it will return first, wait until the triggered asynchronous operation is completed, and then execute the following statements in the function body.

5、 Async / await error handling

The promise object behind the await command may result in rejected, so it’s best to put the await command in the try… Catch code block.Try.. catch error handling is also more consistent with the logic we usually handle when writing synchronization code

async function myFunction() {
  try {
    await somethingThatReturnsAPromise();
  } catch (err) {
    console.log(err);
  }
}

6、 Why is async / wait better?

Async / await has many advantages over promise. Here are three advantages:

1. Simplicity

Using async / await obviously saves a lot of code. We don’t need to write. Then, anonymous functions to handle promise’s resolve value, define redundant data variables, and avoid nested code.

2. Intermediate value

You may have encountered such a scenario, calling promise1, using the results returned by promise1 to call PROMISE2, and then using the results of both to call promise3. Your code is likely to be like this:

const makeRequest = () => {
  return promise1()
    .then(value1 => {
      return promise2(value1)
        .then(value2 => {        
          return promise3(value1, value2)
        })
    })
}

Using async / await, the code becomes extremely simple and intuitive

const makeRequest = async () => {
  const value1 = await promise1()
  const value2 = await promise2(value1)
  return promise3(value1, value2)
}

3. Conditional statements

In the following example, you need to obtain data, and then decide whether to return directly or continue to obtain more data according to the returned data.

const makeRequest = () => {
  return getJSON()
    .then(data => {
      if (data.needsAnotherRequest) {
        return makeAnotherRequest(data)
          .then(moreData => {
            console.log(moreData)
            return moreData
          })
      } else {
        console.log(data)
        return data
      }
    })
}

The code nesting (6 layers) is not readable. They only convey the need to pass the final result to the promise at the outermost layer. Using async / await to write can greatly improve readability:

const makeRequest = async () => {
  const data = await getJSON()
  if (data.needsAnotherRequest) {
    const moreData = await makeAnotherRequest(data);
    console.log(moreData)
    return moreData
  } else {
    console.log(data)
    return data    
  }
}

Author: boating in the waves
Link:Asynchronous solutions promise and wait
Source: GitHub
The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.