I’ve seen about a dozen videos about Promise, and I’ve searched a lot of nuggets articles. But I always feel that I have a little understanding of promise, and I can’t form a knowledge system, and the information on the Internet is too messy. So here’s my understanding of promise.

PromiseA+ Specification

The first is the PromiseA+ specification, which is both a rule and a standard.

When I first started reading Promise, I was so confused by all the articles on the Web that I settled into the PromiseA+ specification. I wanted to see what a standard Promise should have. Read through the PromiseA+ specification translated into Chinese.

Here is the original text and I read the translation address, so that you can learn:

PromiseA+ spec: promisesaplus.com/

PromiseA + specification, malcolmyu. Making. IO/malnote / 201…

Github:github.com/promises-ap…

There is a sentence in the specification:

An open, robust, and universal JavaScript Promise standard. Developed by developers for their reference.

I think this sentence is very important. We do not need a strict and rigid standard. When learning Promise, we should think more about why developers design such a standard and how it is beneficial to our development. And how to make it convenient.

1. First, what are promises

Promise represents the result of an asynchronous operation, and is complemented by the then method, which registers two callback functions, resolve and Reject. Or a promise is an object or a function that has a then method.

2. (fullfill/ resolve)

The sequence of actions that a promise takes when it succeeds.

3. Reject

A sequence of actions that a promise fails.

4. Final Value

Refers to the value passed to the resolution callback when the promise is resolved

The reason for this is that…

Refers to the value passed to the rejection callback when a promise is rejected

6, thenable

Is an object or function that defines the then method

7, value the value

Any valid JavaScript value, including undefined, thenable, and Promise

8, exception

Is a value thrown using the throw statement

9, For reason

Indicate a reason for rejecting a promise.

10. Promise status

(1) Pending state, which translates to “undecided”, means that the state of the current promise has not been changed, and the promise has not succeeded or failed, so it can be migrated to the execution state or rejection state.

(2) Execute the fullfilled/resolved state, when the promise has succeeded and has an immutable end value value

(3) The promise has rejected and has an unchangeable reason

11, then method

(1) The then method is provided to access the promise state

The then method takes two parameters, onFulfule and onRejected

promise.then(onFulfilled, onRejected)
Copy the code

(2) The then method can be called multiple times for example

const p = new Promise((resolve, reject) = > {
        setTimeout(() = > {
            reject(2)},1000);
    }).then(
        value= > {},
        reason= > {}
    ).then(
        value= > {},
        reason= > {}
    ).catch(
        reason= >{})Copy the code

(3) Return of then

The then method must return a Promise object

Note: in this code, the return value of promise1 is resolved whenever it is rejected or resolved, and only rejected if an exception occurs.

const promise2 = new Promise((resolve, reject) = > {
    setTimeout(() = > {
        reject(2)},1000);
}).then(
    value= > {
        console.log("value1 " + value);
    },
    reason= > {
        console.log("reason1 " + reason);
    }
).then(
    value= > {
        console.log("value2 " + value);
    },
    reason= > {
        console.log("reason2 " + reason);
    }
).catch(
    reason= > {
        console.log("catch"); })Copy the code

Why use promsie?

1. Promise is a solution to ASYNCHRONOUS Js programming. Has been incorporated into the specification by ES6.

2. The way callback functions are specified is more flexible

We know that the old callback function had to be specified before starting the asynchronous task,

Now, the promise process goes like this:

Start asynchronous task => Return promise object => Bind callback function to promise object (even after asynchrony)

3, support chain call, can solve the problem of callback hell

(1) What is callback hell? The result of the asynchronous execution of the external callback is the condition for the execution of the nested callback. To put it bluntly, there is endless nesting of callbacks, which makes the whole code very inelegant.

(2) Callback to hell’s shortcomings? Not easy to read/exception handling, bloated code, poor readability, high coupling, poor code reuse

(3) Solutions? Promise chain calls (ultimate solution? Async/await)

Basic use of Promise

As we can see from above, Promise is a solution to ASYNCHRONOUS Js programming, supporting chained calls and solving callback hell. Let’s take a look at the basics.

// create a new Promise object
    const p = new Promise((resolve, reject) = > { // The executor function performs the asynchronous operation synchronous callback
        // 2. Perform asynchronous operations
        setTimeout(() = > {
            const time = Date.now()
            if (time % 2= =0) {
                If successful, call resolve(value)
                resolve('Success data' + time)
            } else {
                Reject (reason)
                reject('Failed data' + time)
            }
        }, 1000);
    })

  p.then(
        value= > { // Successfully receive value data onResolved
            console.log('Successful callback', value)
        },
        reason= > { // Accept the failed reason data onRejected
            console.log('Failed callback', reason)
        }
    )
Copy the code

In addition, we can also use it like this:

 function usePromise(id) {
        return new Promise((resolve, reject) = > {
            if (id == 1) {
                console.log(1)
                resolve(1)}else {
                console.log(false)
                reject(2)
            }
        })
    }
    usePromise(1).then( 
        id= > {
            console.log(id); })Copy the code

In addition, the apis commonly used for promises are listed here as the basis for subsequent handwritten promises

Promise.resolve(value) -- Class method that returns resolved statusPromise.reject(reason) -- A class method that returns rejectedPromise.prototype.then -- Instance method that registers callback functionsPromise.prototype.catch -- Instance method to catch exceptionsPromise.race -- class method that returns the result of the first promise task executedPromise.all -- class method that returns the result of success for all tasks or failure for one of themCopy the code

Fourth, about macro tasks and micro tasks

Macroqueues and microqueues are mentioned here because we need to know about them when we understand the order of Promise’s then execution. I’ll briefly explain these two concepts as they relate to the JavaScript V8 engine, but I won’t go into detail here.

1. Macro tasks:

To coordinate the execution of these tasks methodically on the main thread, the page process introduces message queues and event loops, and the renderer process maintains multiple message queues internally, such as deferred execution queues and regular message queues. The main thread then takes a for loop, continually fetching and executing tasks from these task queues. We call these tasks in the message queue macro tasks.

2. Microtasks:

A microtask is a function that needs to be executed asynchronously, after the completion of the main function but before the completion of the current macro task.

Common macro queue tasks include: DOM event callback, Ajax callback, timer callback Common micro queue tasks include: Promise callback, mutation callback

 setTimeout(() = > { // will be immediately put into the macro queue
            console.log('timeout callback');
        }, 0);
        setTimeout(() = > { // will be immediately put into the macro queue
            console.log('timeout callback');
        }, 0);
        Promise.resolve(1).then(
            value= > { // Will be immediately put into the microqueue
                console.log('Promise onResolved', value)
            }
        )
        Promise.resolve(2).then(
            value= > { // Will be immediately put into the microqueue
                console.log('Promise onResolved', value)
            }
        )
Copy the code

V. Promise exercises

Here are a few simple questions about the order in which promises are executed, which can be easily done by combining macro and microqueues with asynchronous operations. I will not give the specific analysis, if you do not understand the comment can ask or look up information ~~

1, write the result of this code execution:

setTimeout(() = > { // macro queue asynchronous
   console.log(1);
}, 0);
Promise.resolve().then(() = > { // the microqueue is asynchronous
   console.log(2);
})
Promise.resolve().then(() = > { // the microqueue is asynchronous
   console.log(3);
})
console.log(4); / / synchronize
Copy the code

Result: 4 2 3 1

2, write the result of this code execution:

setTimeout(() = > { // macro queue asynchronous
      console.log(1);
}, 0);
new Promise((resolve) = > {
      console.log(2);
      resolve()
}).then(() = > {
      console.log(3);
}).then(() = > {
      console.log(4);
})
console.log(5);
Copy the code

Result: 2 5 3 4 1

3, write the result of this code execution:

const first = () = > (new Promise((resolve, reject) = > {
    console.log(3);
    let p = new Promise((resolve, reject) = > {
        console.log(7);
        setTimeout(() = > {
            console.log(5);
            resolve(6) // Resolve is invalid because it only changes once
        }, 0);
        resolve(1)
    })
    resolve(2)
    p.then((arg) = > {
        console.log(arg); / / 1
    })
}))
first().then((arg) = > {
    console.log(arg); / / 2
})
console.log(4);
Copy the code

Result: 3 7 4 1 2 5

4, write the result of this code execution:

setTimeout(() = > {
    console.log(0);
}, 0);
new Promise((resolve, reject) = > {
    console.log(1);
    resolve()
}).then(() = > {
    console.log(2);
    new Promise((resolve, reject) = > {
        console.log(3);
        resolve()
    }).then(() = > {
        console.log(4);
    }).then(() = > {
        console.log(5);
    })
}).then(() = > {
    console.log(6);
})
new Promise((resolve, reject) = > {
    console.log(7);
    resolve()
}).then(() = > {
    console.log(8);
})
Copy the code

Result: 1 7 2 3 8 4 6 5 0

In addition, as for the important handwritten promise, I am still thinking about how to write it more convenient to remember and use. I hope I can understand it as soon as possible ~~