The introduction
Promise is an asynchronous programming solution that solves callback hell by making chain calls. As the test point of the front-end interview, but also the basic skills of the front-end, it is very important to master its principle. This sharing starts from the use of Promise, step by step analysis of its principle, and finally help you encapsulate your Promise.
Note: If you’re not familiar with Promises, click here to learn the basic Promise syntax.
This article focuses on the following aspects:
- Noncanonical (crude)
Promise
The principle of - The specification (
Promises/A+
)Promise
The principle of
The body of the
So let’s take a look at some of the most commonly used examples and see what the characteristics are.
Using the example
Promise
getNews()
Promise
immediately
resolve
reject
Promise
then
catch
The above code has the following characteristics:
Promise
Is a constructor that takes a function as an argument.- In a function that takes arguments, there are two methods
resolve
andreject
Promise
With the methodthen
andcatch
What about ‘resolve’ and ‘reject’? What does Promise do when it’s instantiated?
Don’t worry, the so-called life and death look pale, refuse to do. Before we answer these two questions, we can directly try to build our own promises
Begin to build
- The constructor
fn
resolve
andreject
So when is fn called? In fact, the Promise instance is called internally when it is initialized, passing in the internal resolve and Reject methods to the developer, as follows:
resolve
reject
Promise
internal
- add
then
andcatch
methods
These two methods are the methods of the Promise instance and should therefore be written on this or Prototype.
Promise
Effect analysis
resolve
和reject
Imagine a scenario where we routinely use Promises, after an asynchronous request, we manually call resolve or Reject to change the state.
resolve
then
reject
catch
then
和catch
The above function is called as follows:
We know that callbacks in the then and catch functions are not executed until resolve is called. So what does it do when we write it this way?
In fact, Promise secretly saves the callbacks we’ve written until we call resolve or Reject manually. In other words, the then and catch elements in a Promise are used to register callbacks and store a list of callbacks until the developer calls them.
So, the then and catch functions should look like this:
resolve
reject
Promise
resolve
reject
then
catch
Chain calls
Next we implement plain chain calls, which are very simple to implement. Since then is the method that is attached to this, we can implement chained calls if we return this directly from then. Something like this:
then
then
okCallback
then
okCallback
okCallback
resolve
then
State introduction and delay mechanisms
In the Promise specification, the initial state is pending, which is fulfilled after the call of resolve and rejected after the call of Reject. The state can only change once.
In addition, to ensure that resolve is fully registered by the time it is called, we should also introduce setTimeout to delay the execution of resolve:
Chain call Promise (emphasis)
In real development, asynchronous requests with sequential requirements are common, and we tend to return a Promise instance in the THEN callback, which means we need to wait for the new Promise instance to resolve before proceeding with the next THEN call.
MyPromise
There’s an easy way to do it, remember what the then function does?
Yes, register a callback.
Since it returns a new Promise and we can’t execute subsequent THEN callbacks, why don’t we just transfer all subsequent THEN callbacks to this new Promise and let it do the execution instead?
Promise
then
return
resolve
then
Have you finished? Finished, here has been able to achieve the Promise of the chain call, that is, today’s 8 minutes you can write your Promise, congratulations!
However, this is not a Promise standard. Do you want to know how the transfer of enforcement rights is addressed in the Promise standard? It’s not complicated, but it will take a lot of patience to understand the logic. Read on when you’re ready
Promises/A+ standard chain call
(To simplify the model, we will analyze only the resolve logic here, which will involve three functions: THEN, Handle, and resolve.)
Then: Instead of returning this, the then function returns a new Promise, which is the bridge between the two “Then” s.
Handle: Registers the callback when the status is pending. Otherwise, call directly.
Resolve: Attempts to iterate through the registered callback to execute. If the argument is an instance of a Promise, the execution is handed over to the new Promise and execution itself is suspended.
Does this look complicated? In fact, it is not complicated, and can be summarized in one sentence:
In promises/A+ specification, the latter promise saves the resolve reference of the former promise.
resolve
resolve
resolve
Promise
resolve
Promise
Promise
resolve
resolve
If that doesn’t make sense, let’s actually look at an example. (Please look at the example and think against the code. The code is in the appendix at the end. It is recommended to paste it into the local editor and think against the code.)
Spongebob from Bikini Beach wants to order a krabby Patty and must first look up the Krabby King’s delivery number online before he can order it. The JavaScript description looks like this:
promise
getPhoneNumber()
then()
then()
getHamburger
Let’s look at the corresponding code execution. Now it’s time to register the callback, and the promise returned by the first THEN will pass its resolve reference to the Handle of getPhoneNumber(), which will store the resolve application along with the corresponding THEN callback:
The second THEN is the same, so after the registration stage, the internal states of each promise are shown in the figure below:
In the call phase, a subsequent resolve is raised with the resolve of getPhoneNumber(), as shown below:
- First of all,
getPhoneNumber()
The triggerresolve
, the return value isnumber
, so the call can be traversedcallbacks
The callback saved in. - Enter the
handle
Delta function, changegetPhoneNumber()
thestate
Then function ① is called, which returnsgetHamburger()
. Call the first onethen
theresolve
Reference, and willgetHamburger()
Passed as a parameter. - Look to the first one
then()
. Parameter in judgmentgetHamburder()
Is aPromise
After the instance, add its ownresolve
It is called as a callbackthen
Method (as you can see in the figure above,getHamburger
thecallbacks
It’s actually the previous onethen
theresolve
Reference, because at this time the previousPromise
Is interrupted, so when the developer callsgetHamburger()
theresolve
Method before continuing unfinishedresolve
To perform. - Wait until the
getHamburger()
theresolve
When called, the previous one is actually calledthen
theresolve
, the return value is passed as an argument to the right-hand sidethen
To make itresolve
- Look at the first one again
then()
On. Into oneselfhandle
Method, changestate
Then function ② is called, triggering the secondthen()
On the far right of the image aboveresolve
- Finally, call the last one
then()
theresolve
(That is, small in the figure abovethen()
thethen()
Is generated automatically by code calls. , the whole asynchronous process ends.
conclusion
Promise uses a resolve function to save us from callback hell (since callbacks are already registered and saved chained), essentially doing a layer of encapsulation. The hardest part to understand is the chain invocation of Promise. The first method I’m going to share with you is pretty straightforward: just pass an outstanding callback to the next Promise. In the second way, multiple then functions are linked together by a resolve reference. The first resolve will likely lead to a series of subsequent resolves, like dominoes.
The appendix
Promises/A+ Code Examples (Source: Cf [1])
function MyPromise(fn) {
var state = 'pending',
value = null,
callbacks = [];
this.then = function (onFulfilled) {
return new MyPromise(function (resolve) {
handle({
onFulfilled: onFulfilled || null,
resolve: resolve
})
})
}
let handle = (callback) => {
if (state === 'pending') {
callbacks.push(callback)
return} / / ifthenNothing is passed inif(! callback.onFulfilled) { callback.resolve(value)return
}
var ret = callback.onFulfilled(value)
callback.resolve(ret)
}
let resolve = (newValue) => {
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
var then = newValue.then
if (typeof then= = ='function') {
then.call(newValue, resolve)
return
}
}
state = 'fulfilled'
value = newValue
setTimeout(function () {
callbacks.forEach(function (callback) {
handle(callback)
})
}, 0)
}
fn(resolve)
}
Copy the code
reference
- 30 minutes, let you thoroughly understand the principle of Promise
- Nodejs Pu Ling P90