Promise

A better unified solution for asynchronous programming, but directly using traditional callback methods to complete complex asynchronous processes will cause a lot of callback problems (callback hell). CommonJS community proposed the specification Promise, which aims to provide a more reasonable and standardized unified solution for asynchronous programming, and was standardized in ES2015. Become a language specification.

A Promise is an object that indicates whether an asynchronous task will eventually succeed or fail, like an internal Promise to the outside world, This promise is gradually postponed, which is a big pity at the beginning. At the end, there may be onFulfilled which is the corresponding callback function of success and onRejected, which is also a big pity.

Example:

    // Promise accepts a function with two arguments (both functions), resolve and reject
    const promise = new Promise(function (resolve, reject) {
        // The effect of the resolve function is to change the state of the Promise to depressing
        // The result of success is passed through resolve
        resolve(100)
        
        The reject function changes the state of Promise to Rejected
        // The result of a failure is passed through the reject
        The reject argument is generally an error object that describes the cause of the error
        reject(new Error('promise rejected'))
    })
    
    promise.then(function(value) {
        // This callback is called when resolve is returned
        console.log('resolve', value) / / = > 100
    }, function(err) {
        This callback is called when reject is returned
        console.log('rejected', err) // => Error object
    })
Copy the code

Promise chain call

  • The then method of the Promise object returns a brand new Promise object
  • The subsequent THEN method registers the callback for the Promise returned by the previous THEN
  • The return value of the callback function from the previous THEN method is used as an argument to the callback from the later THEN method
  • If a Promise is returned in the callback, then callbacks to subsequent then methods wait for it to end

Exception handling for promises

OnRejected does some processing for exceptions in the Promise, such as: The Promise calls the Reject method, calls a non-existing method, and throws an Error exception.

Catch exceptions through the Promise catch method

    promise.then(function(value) {
        // This callback is called when resolve is returned
        console.log('resolve', value) / / = > 100
    })
    .catch(function(err) { // The catch method is just another name for reject
        This callback is called when reject is returned
        console.log('rejected', err) // => Error object
    })
Copy the code

The second argument to the catch not then method catches the difference between exceptions:

  • A catch catches an exception that occurred in the previous THEN method
  • The second argument to the then method catches the exception that is present in the current Promise

If an exception occurs in the Promise chain, the exception is passed back until it is caught, so the catch method is more like registering an exception catch for the entire chain.

A static method for Promise

The resolve method returns the value directly

Example:

    Promise.resolve('foo')
        .then(function(value) {
            console.log(value) // => foo
        })
    
    // The value above is the same as the value below
    new Promise(function(resolve, reject) {
        resolve('foo')})Copy the code

Wrap a Promise using the static resolve method of the Promise object to get an example of the wrapped Promise:

    let promise = ajax('/api/users.json')
    let promise2 = Promise.resolve(promise)
    console.log(promise === promise2) // => true
Copy the code

Promise’s resolve method returns an object with the THEN method. When this object also has the ondepressing method, we can also use the THEN method to get the returned value example:

    Promise.resolve({
        then: function(onFulfilled, onRejected) {
            onFulfilled('foo')
        }
    })
    .then(function(value) {
        console.log(value) // => foo
    })
Copy the code

Reject (new Error(‘ XXX ‘)); resolve (‘ reject ‘); reject(‘ XXX ‘))

Promise parallel execution

Promise.all

When multiple asynchronous tasks need to be processed at the same time, a counter is defined to determine whether all asynchronous tasks are completed. Promise now gives us a method that can handle multiple asynchronous tasks simultaneously: All.

Example:

    let promise = Promise.all([
        ajax('/api/users.json'),
        ajax('/api/posts.json')])// The all method returns a Promise object when all asynchronous tasks have completed
    Resolve is returned only if all asynchronous tasks succeed, reject otherwise
    peomise.then(function(value) {
        // Value is passed as an array containing the execution results of all asynchronous tasks
        console.log(value) // => [xx, xx]
    })
Copy the code

Promise.race

The RACE method can also combine multiple Promise objects into a new Promise object. Unlike the All method, the ALL method waits for all asynchronous tasks to end. The RACE method only waits for the first asynchronous task to finish, meaning that the race method will finish as soon as any of the asynchronous tasks complete.

Example:

    const request = ajax('/api/posts.json')
    const timer = new Promise((resolve, reject) = > {
        setTimeout((a)= > reject(new Error('timeout')), 500)})Promise.race([
        request,
        timer
    ])
    .then(value= > {
        // if the request method succeeds within 500ms, a successful callback is executed
        console.log(value)
    })
    .catch(err= > {
        // if the request method fails within 500ms, the callback fails
        console.log(err)
    })
Copy the code

Promise execution timing

Callback queue task is often referred to as macro, macro task execution process may add some additional requirements, the newly added requirements can be selected as a new macro task into the queue queue, setTimeout will line up in the macro task, for example, can also act as a micro task, directly executed immediately after the end of the current task. The Promise callback is executed as a microtask, immediately at the end of this call. Microtasks: To improve overall responsiveness, most asynchronous calls are currently executed as macro tasks, while Promise objects, MutationObserver, and Process. nextTick in Node are executed as microtasks

Example:

    console.log('begin')
    
    // Execute as macro task
    setTimeout((a)= > {
        console.log('timer')},0)
    
    // Execute as a microtask
    Promise.resolve()
        .then((a)= > {
            console.log('promise')
        })
        .then((a)= > {
            console.log('promise2')})console.log('end')
    
    // => begin => end => promise => promise2 => timer
Copy the code