One Catalog
No frills front end , What's the difference with salted fish
[](url)
Two Preface
Return directory
This article will combine Promise
Knowledge point + Training questions in the form of explanation .
Pre knowledge points :
If you don't know these knowledge points well , Please click to view , Avoid being possessed by the devil .
2.1 Thinking about it
Return directory
JavaScript The evolution of asynchronous solutions in , It's in the following order :
callback -> promise -> generator -> async/await
In the computer industry , There is a myth of simple reductionism :
- The closer you get to the bottom , The higher the technical content .
- Every programmer has the pursuit of understanding the underlying source code .
This is true to a certain extent .
however , We should see that too , Once between the bottom and the surface , There's a domain gap . Master the bottom , It doesn't mean at the surface level .
For example, game developers , Not necessarily the best in the game . This is in FPS Especially in shooting or fighting games , Most of the top players in these games , I can't write code at all .
If you will be proficient in Promise
Defined as , Good at using in various asynchronous scenarios Promise
solve the problem .
that , Be able to write Promise
Realization , Proficient in Promise
It doesn't help much .
It comes from the official account of WeChat : Industrial Agglomeration
2.2 reference
Return directory
Please understand that this is a job 2 More than years of small front-end finishing , May ignore some of the essence of big guy articles. , In order to make an inappropriate order .
The following articles do not rank in any order , It's just personal comparison , There is not a trace of denigration , All the articles are read with worship .
good :
- [x] ES6 introduction - Promise object 【 Reading suggestions :2h】
- [x] Come as soon as you want 45 Avenue Promise The interview questions are good to the end 【 Reading suggestions :8h】
- [x] Interview highlights Promise【 Reading suggestions :20min】
Handwriting Promise:
- [x] The simplest way to achieve Promise, Support asynchronous chain call (20 That's ok )【 Recommended reading :20min】
- [x] BAT Front end classic interview questions : The most detailed handwriting in history Promise course 【 Reading suggestions :30min】
- [x] 100 Line code implementation Promises/A+ standard 【 Reading suggestions :30min】
- [x] Learn to make wheels together ( One ): Write a match from scratch Promises/A+ canonical promise【 Reading suggestions : skimming 】
- [x] Promise Realization principle ( Source code attached )【 Reading suggestions : skimming 】
- [x] analyse Promise internal structure , Step by step to achieve a complete 、 Through all Test case Of Promise class 【 Recommended reading : skimming 】
- [x] Xiao Shao teaches you to play promise Source code 【 Recommended reading : skimming 】
- [x] Promise Can't ?? Look here !!! The most accessible thing in history Promise!!!【 Recommended reading : skimming 】
Promises/A+ standard :
- [x] Promises/A+ standard ( Chinese version 【 Reading suggestions : nothing 】
- [x] Promises/A+ standard ( English version )【 Reading suggestions : nothing 】
- [x] Promises/A+ Test warehouse 【 Reading suggestions : nothing 】
Add experience to :
- [x] ES6 And Promise Frequently asked questions 【 Reading suggestions :10min】
- [x] Promise Will know ( Ten questions )【 Reading suggestions :10min】
- [x] Explain in vernacular Promise( One )【 Reading suggestions :30min】
3、 ... and Promise On
Return directory
3.1 What is it?
Return directory
What is? Promise
?
Let's just print it out :
console.dir(Promise);
/*
Promise(
all: ƒ all()
arguments: (...)
caller: (...)
length: 1
name: "Promise"
prototype: Promise {constructor: ƒ, then: ƒ, catch: ƒ, finally: ƒ, Symbol(Symbol.toStringTag): "Promise"}
race: ƒ race()
reject: ƒ reject()
resolve: ƒ resolve()
Symbol(Symbol.species): (...)
Symbol(allSettled): ƒ (d)
get Symbol(Symbol.species): ƒ [Symbol.species]()
__proto__: ƒ ()
[[Scopes]]: Scopes[0]
)
*/
Yes ,Promise
It's a constructor .
It's that simple , Don't think about other things , Whether it works or not is the key .
3.2 Why?
Return directory
Why Promise
?
Look at a piece of code :
const action = () => {
setTimeout(() => {
ajax('http://www.xxx.com/getData', (text) => {
if (text === 'hello') {
doSomething2();
} else if (text === 'world') {
doSomething3();
}
})
}, 500);
};
action();
doSomething1();
This is called back to hell code :
- perform
action
, takesetTimeout
Put in the macro task queue - perform
doSomething1()
, Execute the code inside - 500ms Or later , perform
ajax
, Waiting for completion ajax
After completion , Judgetext
, And then performdoSomething2()
perhapsdoSomething3
.
It certainly doesn't seem easy , Because when doSomething
The code inside will be enriched again , You don't look carefully , I don't know how this code will go .
Let's do another example :
request 1(function( Request the results 1){
request 2(function( Request the results 2){
request 3(function( Request the results 3){
request 4(function( Request the results 4){
request 5(function( Request the results 5){
request 6(function( Request the results 3){
...
})
})
})
})
})
})
Do you feel numb on your scalp .
The negative effects of callback to hell are as follows :
- Code bloated .
- Poor readability .
- The coupling is too high , Poor maintainability .
- Poor code reusability .
- Easy to breed bug.
- Exceptions can only be handled in callbacks .
therefore , To deal with this pain , This requires a commitment :
- Give something to someone , When this man is done , Failure or success , Will give you a response , So that you can safely leave it to it .
This man is called Promise
, Let's take a look at its intuitive function :
function getData() {
const p = new Promise((resolve, reject) => {
// Ajax Request etc.
setTimeout(() => {
console.log(' Data acquisition success ');
resolve(' Data after successful input ');
}, 1000);
});
return p;
}
getData().then((res) => {
// Get data , And then deal with it
console.log(res);
// If there's still Ajax request , So keep calling
// getData2()
});
So we can play with ease .
3.3 How to use it?
Return directory
Promise
Use , It's not hard to say , Let's go straight to the code :
// 1. Set up a promise
const promise = new Promise((resolve, reject) => {
// 2. Set up a 0-10 random number
const number = Math.floor(Math.random() * 10);
// 3. If this number is greater than 5, Let's take it as a success
if (number > 5) {
resolve(' Greater than 5'); // resolve It means to solve
} else { // 4. Otherwise, it will be a failure
reject(' Less than 5'); // reject It means to deal with failure
}
});
// 5. If it is resolve, Then go .then; If it is reject, Then go .catch
promise.then((res) => {
console.log(' success :', res);
}).catch((error) => {
console.log(' Failure :', error);
}).finally(() => {
// 6. Be careful finally It means the end of the play , Whether it's a good ending or a bad ending , It's the end
console.log(' No matter what happened ahead , I will call ');
});
Its output :
Output 1
Failure : Less than 5
No matter what happened ahead , I will call
Output 2
success : Greater than 5
No matter what happened ahead , I will call
Because we use random values , So the above 2 All kinds of outputs are possible .
As for the... In it resolve
、reject
、.then()
、.catch()
、.finally()
, We don't care about , I'll talk about it later , Just ask yourself if you understand the previous one ?
If you understand , So congratulations on Promise
With a simple understanding .
Four Promise Basics
Return directory
4.1 new Promise
Return directory
First , Let's take a look at how to walk a new Promise
:
const promise = new Promise((resolve, reject) => {
console.log(resolve); // [Function]
console.log(reject); // [Function]
});
console.log(promise); // Promise { <pending> }
then , We distinguish these concepts :
Promise
An object is a constructor , Used to generatePromise
example , thereforenew Promise()
Not surprisingly enough .new Promise()
Pass in a function , This function can take 2 Parameters :resolve
andreject
.resolve
The role of thePromise
Object state from “ Hang in the air ” Turn into “ success ”(pending -> resolved
)reject
The role of thePromise
Object state from “ Hang in the air ” Turn into “ Failure ”(pending -> rejected
)- No execution at
resolve
andreject
Before , They're stillpending
Of .
Last , It must be said that , My friends have a clear idea of this .
So let's take a look at Promise
The state of .
4.2 Promise state
Return directory
Promise
Yes 3 States :pending
、fulfilled
、rejected
- The initial state :
pending
- Success status :
fulfilled
( The actual print will seeresolved
) - Failure status :
rejected
If you are in the new Promise
Used in China resolve()
, Then it will go .then()
;
If you're using a reject()
, Then it goes .catch()
.
How to put it? ?
const promise1 = new Promise((resolve, reject) => {
resolve(' success ');
});
promise1.then((res) => {
console.log('res 1:', res);
}).catch((error) => {
console.log('error 1:', error);
})
const promise2 = new Promise((resolve, reject) => {
reject(' Failure ');
});
promise2.then((res) => {
console.log('res 2:', res);
}).catch((error) => {
console.log('error 2:', error);
})
In this code , Its output is :
res 1: success
error 2: Failure
It's easy to understand , because promise1
go resolve
and promise2
go reject
.
Promise
Once the state of is changed, it cannot be changed again .
Look at the code below :
const promise = new Promise((resolve, reject) => {
resolve(' success 1');
reject(' Failure ');
resolve(' success 2');
});
promise.then((res) => {
console.log('res:', res);
}).catch((err) => {
console.log('err:', err);
});
Output what ?
Yes, the output is :res: success 1
.
a promise is weightier than one thousand bars of gold , You agreed to introduce your sister to me , I'll tell you later , How can this be done .
Crazy hints
Again ,Promise
It's not allowed to return :
- You change the status to
resolved
, Then don't try to change it , Let's go.then()
Well !
OK, See here, you're right Promise
The foundation has a certain understanding , Let's go to the question !
5、 ... and Question bank : Basic questions
Return directory
before this , Once again Event Loop
.
Event Loop
Execution order :
- At first, the whole script
script
Execute as a macro task - In the process of execution , Synchronization code Direct execution , Macro task Enter the macro task queue , Micro task Enter the micro task queue .
- The current macro task is out of the team , Check the list of micro tasks , If there is one, execute it in turn , Until it's all done .
- Execute browser UI Rendering of threads .
- Check if there is
Web Worker
Mission , If there is one, carry out . - Finish this round of macro tasks , Back to step 2, In turn, cycle , Until the macro and micro task queues are empty .
Micro task Include :
MutationObserver
Promise.then()/catch()
- With
Promise
Other technologies developed for the foundation , for examplefetch API
- V8 The garbage collection process
- Node Unique
process.nextTick
Macro task Include :
script
setTimeout
setInterval
setImmediate
I/O
UI rendering
For example, a piece of code :
const promise = new Promise((resolve, reject) => {
console.log('1');
resolve('2');
});
setTimeout(() => {
console.log('3');
}, 0);
promise.then((res) => {
console.log(res);
});
Output :1 -> 2 -> 3
.
How do you understand that ?
At the beginning of all tasks , Because macro tasks includescript
, So the browser will first perform a macro task , The delayed tasks you see in the process ( for examplesetTimeout
) It will be executed in the next macro task .
- Go ahead
script
. - meet
promise = new Promise
, Go straight inside . - Print out 1.
- meet
resolve()
, takePromise
Status changed toresolved
, takePromise.then()
throw sth. intoscript
In the micro task queue under this macro task . - here
script
The micro task queue under macro task includes :promise.then()
. - meet
setTimeout()
, Put it in the macro task queue . - At this point, the macro task queue has :
script
、setTimeout
. - Synchronization task completed .
- Check the current macro task
script
Next micro task , And circle out of the team . - Output
2
. - Macro task
script
There's nothing that can be executed , Go to the next macro tasksetTimeout
. - Output
3
. - The macro task queue is finished , Code execution completed .
Simply speaking :
- Go ahead
script
. - Macro tasks encountered
setTimeout
Wait for the back , etc.script
Go out of the team after you've gone . - See the current macro task for the micro task encountered , yes
script
Just throw it awayscript
Inside , yessetTimeout
Just throw it awaysetTimeout
Inside . - Each macro task completes the synchronization task and the micro task , Just go to the next macro task .
- Cycle steps 4.
It's that simple , It's no use saying more , Brush the title to deepen my impression !
5.1 Topic 1
Return directory
const promise = new Promise((resolve, reject) => {
console.log('promise');
});
console.log('1', promise);
/*
The output sequence is analysis :
Output :
* promise
* 1 Promise { <pending> }
analysis :
1. From top to bottom , meet new Promise, Output 'promise'
2. Output '1' and promise current state
*/
5.2 Topic two
Return directory
const promise = new Promise((resolve, reject) => {
console.log(1);
resolve('success');
console.log(2);
});
promise.then(() => {
console.log(3);
})
console.log(4);
/**
Output process and Analysis :
Output :1 -> 2 -> 4 -> 3
analysis :
1. From the top down , meet new Promise, Go ahead 1
2. meet resolve, change Promise state
3. Output 2
4. meet .then(), Throw it into a micro task
5. Output 4
6. Come back to the steps 4 The micro task of , Output 3
*/
5.3 Topic three
Return directory
const promise = new Promise((resolve, reject) => {
console.log(1);
console.log(2);
});
promise.then(() => {
console.log(3);
})
console.log(4);
/**
Output process and Analysis :
Output :1 -> 2 -> 4
analysis :
1. From the top down , meet new Promise, Go ahead 1
2. Keep going , Output 2
3. meet .then(), because new Promise Not in China resolve, So you don't throw it into a micro task
4. Output 4
*/
5.4 Topic four
Return directory
const promise1 = new Promise((resolve, reject) => {
console.log('promise1');
resolve('resolve1');
})
const promise2 = promise1.then((res) => {
console.log(res);
});
console.log('1', promise1);
console.log('2', promise2);
/**
Output sequence and Analysis :
Output :
* promise1
* 1 Promise { <resolve>: 'resolve1' }
* 2 Promise { <pending> }
* resolve1
analysis :
1. meet new Promise, Output promise1
2. meet resolve, change Promise state , And save the results
3. meet promise1.then, Put it in the micro task queue
4. promise2 It's a new state of being pending Of Promise
5. Output 1 and promise1, At present promise1 The status of is resolve, And it exists 'resolve1'
6. Output 2 and promise2, At present promise2 The status of is peding
7. Macro task finished , Perform micro tasks , Output resolve1
*/
5.5 Topic 5
Return directory
const fn = () => (new Promise((resolve, reject) => {
console.log(1);
resolve('success');
}));
fn().then((res) => {
console.log(res);
})
console.log('start');
/**
Execution order and parsing :
The order :
* 1
* 'start'
* 'success'
analysis :
1. fn Is an immediate execution function , So it's going to execute first new Promise, So the output 1
2. meet resolve, take Promise State change
3. meet .then(), Because the front changed the State , So it's going to be put into micro tasks
4. Output 'start'
5. Macro task finished , Perform micro tasks , Output 'success'
*/
5.6 Topic 6
Return directory
const fn = () => {
return new Promise((resolve, reject) => {
console.log(1);
resolve('success');
})
};
console.log('start');
fn().then((res) => {
console.log(res);
});
/**
Execution order and parsing :
The order :
* 'start'
* 1
* 'success'
analysis :
The last problem is to execute the function immediately , The problem is not
So in the fn() When called , Will execute new Promise
*/
6、 ... and Question bank : combination setTimeout
Return directory
About macro tasks setTimeout
, We are going to give an example of a classic problem :
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 0);
}
The output of this problem :
3
3
3
from Event Loop
From the perspective of :
- Take the synchronous task ,
var i
The traversal is finished ,i = 3
(var
Variable pollution ). for()
While traversing , take 3 individualsetTimeout
Into the macro task .script
This macro task is finished .- Execute sequentially 3 individual
setTimeout
, Because at this timei
by3
, So it will output in turn 3 individual 3.
Of course , The solution is simple :
- Method 1 : Set immediate execution function
By setting the way the function is executed immediately , Form a block scope , solve i
The pollution problem of .
for (var i = 0; i < 3; i++) {
(function(i) {
setTimeout(() => {
console.log(i);
}, 0);
})(i);
}
- Method 2 : Set up let
let
Will make for
Form a block scope , To prevent pollution , solve the problem .
for (let i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 0);
}
Of course ,setTimeout
There's another problem :
setTimeout(() => {
console.log(1);
}, 0);
setTimeout(() => {
console.log(2);
}, 1000);
setTimeout(() => {
console.log(3);
}, 500);
What does this code output ?
1
3
2
setTimeout
receive 2 Parameters :
function()
: Callback function . Execute after the time specified by the second parameter .timer
: execution time ( millisecond ). stayn
The callback function is executed in milliseconds .
Generally speaking , Macro tasks follow the rules of the queue , Come in and out in order , This should output :1 -> 2 -> 3
.
This is in timer
It's true under the same circumstances .
however , stay timer
In different situations , Need to follow Priority queue The way to join the team :
- Who is the youngest , Who is in front .
So the order of output here is :1 -> 3 -> 2
.
You don't need to understand
Priority queue What is it , You want to respect the old and love the young ,
timer
The smaller, the more ahead .
OK, About setTimeout
Related knowledge jsliang Introduction completed , Let's look at the problem !
6.1 Topic 1
Return directory
console.log('start');
setTimeout(() => {
console.log('time');
});
Promise.resolve().then(() => {
console.log('resolve');
});
console.log('end');
/**
Execution sequence and Analysis :
The order :
* 'start'
* 'end'
* 'resolve'
* 'time'
analysis :
1. remember script and setTimeout It's a macro task
2. First, execute script
3. Output 'start'
4. meet setTimeout, Put it in the macro task queue
5. meet Promise, then Promise become resolve() Post state , Yes .then(), So put it in the micro task queue
6. Output 'end'
7. Traverse this micro task queue , The output step 5 The content of , namely 'resolve'
8. step 7 Walk the , Execute the next macro task queue , Output 'time'
*/
6.2 Topic two
Return directory
const promise = new Promise((resolve, reject) => {
console.log(1);
setTimeout(() => {
console.log('timerStart');
resolve('success');
console.log('timerEnd');
}, 0);
console.log(2);
});
promise.then((res) => {
console.log(res);
});
console.log(4);
/**
Execution sequence and Analysis :
The order :
* 1
* 2
* 4
* 'timerStart'
* 'timerEnd'
* 'success'
analysis :
1. remember script and setTimeout It's a macro task
2. First, execute script This macro task
3. meet new Promise, Output 1
4. meet setTimeout, Put in the macro task queue
5. Output 2
6. meet .then(), But there's no key (resolve), skip
7. Output 4
8. Currently, there are no micro tasks , Execute the next macro task setTimeout
9. Output 'timerStart'
10. Promise meet resolve, Change state , indicate .then() It's time to put in micro tasks
11. Output 'timerEnd'
12. Execute macro task setTimeout Next micro task , namely Promise.then()
13. Output 'success'
*/
6.3 Topic three
Return directory
setTimeout(() => {
console.log('timer1');
setTimeout(() => {
console.log('timer3');
}, 0);
}, 0);
setTimeout(() => {
console.log('timer2');
}, 0);
console.log('start');
/**
Execution sequence and Analysis :
The order :
* 'start'
* 'timer1'
* 'timer2'
* 'timer3'
analysis :
1. remember script and setTimeout It's a macro task
2. First, execute script This macro task
3. Meet the first one setTimeout, Put it in the macro task queue
4. there setTimeout For export 'timer1' A whole of setTimeout, At this point, it doesn't go into it to execute code
5. Meet the second one setTimeout, Put it in the macro task queue
6. Output 'start'
7. Look at micro tasks , There are no micro tasks
8. View macro task queue , Yes 2 individual , They are output time1 and timer2 Of
9. First of all setTimeout Outgoing queue , Output 'timer1'
10. Meet the third one setTimeout, Put it in the macro task queue , After the second
11. first setTimeout No micro tasks , So this macro task is finished
12. the second setTimeout Outgoing queue , Output 'timer2'
13. It doesn't use micro tasks at this point , So this macro task is finished again
14. Third setTimeout Outgoing queue , Output 'timer3'
15. The third one doesn't work either , So it's done
16. At this point, the macro task queue is executed , Call it a day
*/
6.4 Topic four
Return directory
setTimeout(() => {
console.log('timer1');
Promise.resolve().then(() => {
console.log('promise');
});
}, 0);
setTimeout(() => {
console.log('timer2');
}, 0);
console.log('start');
/**
Execution sequence and Analysis :
The order :
* 'start'
* 'timer1'
* 'promise'
* 'timer2'
Be careful :node V10.16.0 The output version of is different
analysis :
1. remember script and setTimeout It's a macro task
2. First, execute script This macro task
3. Meet the first one setTimeout, Put it in the macro task queue
4. there setTimeout For export 'timer1' A whole of setTimeout, At this point, it doesn't go into it to execute code
5. Meet the second one setTimeout, Put it in the macro task queue
6. Output 'start'
7. Look at micro tasks , There are no micro tasks , So execute the next macro task
8. View macro task queue , Yes 2 individual , They are output time1 and timer2 Of
9. First of all setTimeout Outgoing queue , Output 'timer1'
10. meet Promise.then(), Put it in the micro task queue at this time
11. step 10 The first one is stored setTimeout A micro task of , Execute and output 'promise'
12. the second setTimeout Outgoing queue , Output 'timer2'
13. It doesn't use micro tasks at this point , So this macro task is finished again
14. At this point, the macro task queue is executed , Call it a day
*/
6.5 Topic 5
Return directory
Promise.resolve().then(() => {
console.log('promise1');
const timer2 = setTimeout(() => {
console.log('timer2');
}, 0);
});
const timer1 = setTimeout(() => {
console.log('timer1');
Promise.resolve().then(() => {
console.log('promise2');
});
}, 0);
console.log('start');
/**
Execution sequence and Analysis :
The order :
* 'start'
* 'promise1'
* 'timer1'
* 'promise2'
* 'timer2'
analysis :
1. remember script and setTimeout It's a macro task
2. First, execute script This macro task
3. meet Promise.then(), Push it into the micro task queue , Be careful not to execute the contents
4. meet timer1, Push it to the macro task queue
5. Output 'start'
6. see script Macro task queue in , Find out Promise.then(), Push it out for execution
7. Output 'promise1'
8. meet timer2, Push it to the macro task queue
9. script There are no remaining micro tasks , So continue to traverse the macro task
10. Discovery queue [timer1, timer2], According to the first in first out principle , Introduction timer1
11. Output 'timer1', Discover micro tasks Promise.then(), Push it forward timer1 Micro task queue of
12. Output `promise2`
13. Continue to execute macro task queue , Out of the team timer2, Output 'timer2'
*/
6.6 Topic 6
Return directory
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success');
}, 0);
});
const promise2 = promise1.then(() => {
throw new Error('error!');
});
console.log('promise1-1', promise1);
console.log('promise2-1', promise2);
setTimeout(() => {
console.log('promise1-2', promise1);
console.log('promise2-2', promise2);
}, 0);
/**
Execution sequence and Analysis :
The order :
* 'promise1-1' Promise { <pending> }
* 'promise2-1' Promise { <pending> }
* 'promise1-2' Promise { <resolve>: 'success' }
* 'promise2-2' Promise { <reject>: Error: error! }
Be careful : stay Node v10.16.0 The result of running on is different
analysis :
1. remember script and setTimeout It's a macro task
2. First, execute script This macro task
3. meet promise1 here , perform new Promise What's in it , Will bring resolve Of setTimeout Push macro task queue
4. meet promise2, Because I haven't entered yet resolve state , So here we ignore
5. Two consecutive lines of output , because promise1 and promise2 They haven't been dealt with yet , So it is peading state
6. Meet the second one setTimeout, Push it into the macro task queue
7. View macro task queue , Launch the first setTimeout, take Promise Status changed to resolve
8. perform promise2, change promise2 The status of is reject
9. first setTimeout completion of enforcement , Execute the second setTimeout
10. The output step 8 and step 9 Medium Promise state
*/
6.7 Topic 7
Return directory
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success');
console.log('timer1');
}, 0);
console.log('promise1 What's in it ');
});
const promise2 = promise1.then(() => {
throw new Error('error!');
});
console.log('promise1-1', promise1);
console.log('promise2-1', promise2);
setTimeout(() => {
console.log('timer2');
console.log('promise1-1', promise1);
console.log('promise2-2', promise2);
}, 0);
/**
Execution sequence and Analysis :
The order :
* 'promise1 What's in it '
* 'promise1-1' Promise { <pending> }
* 'promise2-1' Promise { <pending> }
* 'timer1'
* 'timer2'
* 'promise1-2' Promise { <resolve>: 'success' }
* 'promise2-2' Promise { <reject>: Error: error! }
Be careful : stay Node v10.16.0 The result of running on is different
analysis :
The type of the following question is similar , I'm not going to do the analysis here
*/
7、 ... and .then() Chain operation
Return directory
7.1 Two parameters
Return directory
In the title above , We got to know .then()
, But we didn't go into details , So here we will explain them one by one .
Don't talk much , Look at the code first :
const promise1 = new Promise((resolve, reject) => {
resolve('1');
});
promise1.then(
(res) => {
console.log('res:', res);
}, (err) => {
console.log('err:', err);
}
)
const promise2 = new Promise((resolve, reject) => {
reject('1');
});
promise2.then(
(res) => {
console.log('res:', res);
}, (err) => {
console.log('err:', err);
}
)
What does it output :
res: 1
err: 1
therefore , actually .then()
It's reception 2 Parameters :
resolved
: If we set it upresolved
state , Then we'll take the first parameter .rejected
: If we set it uprejected
state , Then we'll take the second parameter .
This is the first 2 Parameters and .catch()
It's almost the same .
however , To keep the code sizable , It is suggested that the second parameter be changed to .catch()
, Easy to understand .
7.2 call chaining
Return directory
stay Promise.then()
In the method ,.then()
It can be called in chain .
Promise.resolve(1).then((res1) => {
console.log('res 1:', res1); // res 1: 1
return res1;
}).then((res2) => {
console.log('res 2:', res2); // res 2: 1
})
You can see , next .then()
, You can receive the last one .then()
in return
What's coming out .
Of course , It is worth noting that , If we don't return res1
, So the output becomes :res 2: undefined
.
such , If we need to do some asynchronous operations , Then you can use this method .
Don't talk much , On the first code :
const red = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(' red ');
resolve(' The red light is over ');
}, 1000);
});
}
const green = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(' green ');
resolve(' The green light is gone ');
}, 1000);
});
}
red().then((res1) => {
console.log('res1:', res1);
return green();
}).then((res2) => {
console.log('res2:', res2);
})
/*
1s Post output :
red
res1: The red light is over
2s Post output :
green
res2: The green light is gone
*/
Here , Red light back to a Promise
object , etc. setTimeout
Walk the , The status changes to resolved
, Then go .then()
, then 1s Post output : red -> res1: The red light is over
.
next , We will green()
Yes , And return it to return
To the next one .then()
.
therefore , We will be in 2s Post output green -> The green light is gone
.
This is it. .then()
The door of the road .
8、 ... and .catch() Capture problem
Return directory
We mentioned above :
reject
The role of thePromise
Object state from “ Hang in the air ” Turn into “ Failure ”(pending -> rejected
)
and .then()
Of the 2 Parameters and .catch()
It's the same thing , It's all about capturing failed content .
const getRandom = new Promise((resolve, reject) => {
const number = Math.random() * 10; // Generate 1-10 Number of ranges
if (number > 5) {
reject(' Number exceeds 5');
} else {
resolve(' Number less than 5');
}
});
// Capture error mode one : Use catch()
getRandom.then((res) => {
console.log('res:', res);
}).catch((error) => {
console.log('error:', error);
});
// Capture error mode 2 :then() There are two parameters
getRandom.then(
(res) => { // Equate to then()
console.log('res:', res);
}, (error) => { // Equate to catch()
console.log('error:', error);
},
);
/*
Output :
* res: Number less than 5
* error: Number exceeds 5
Random one of the two
*/
Of course , In order to read well , Recommended or used .then().catch()
The way , Not through .then()
The inside number 2 Parameters to represent .
Nine .finally() Enforcement
Return directory
finally
Method is used to specify whether Promise
What is the final state of the object , Will perform the operation .
meanwhile ,.finally()
Method does not take any arguments , Because it's enforcement , Don't rely on Promise
The results of the implementation of .
It's essentially .then()
A special case of the method .
// 1. Set up a promise
const promise = new Promise((resolve, reject) => {
// 2. Set up a 0-10 random number
const number = Math.floor(Math.random() * 10);
// 3. If this number is greater than 5, Let's take it as a success
if (number > 5) {
resolve(' Greater than 5'); // resolve It means to solve
} else { // 4. Otherwise, it will be a failure
reject(' Less than 5'); // reject It means to deal with failure
}
});
// 5. If it is resolve, Then go .then; If it is reject, Then go .catch
promise.then((res) => {
console.log(' success :', res);
}).catch((error) => {
console.log(' Failure :', error);
}).finally(() => {
// 6. Be careful finally It means the end of the play , Whether it's a good ending or a bad ending , It's the end
console.log(' No matter what happened ahead , I will call ');
});
Let's take the code at the beginning to review .finally()
Well :
Output 1
Failure : Less than 5
No matter what happened ahead , I will call
Output 2
success : Greater than 5
No matter what happened ahead , I will call
Because we use random values , So the above 2 All kinds of outputs are possible .
however , No matter what kind of output ,.finally()
It will come out .
Ten Question bank :.then()、.catch()、.finally()
Return directory
10.1 Topic 1
Return directory
const promise = new Promise((resolve, reject) => {
resolve('success1');
reject('error');
resolve('success2');
});
promise.then((res) => {
console.log('then1: ', res);
}).then((res) => {
console.log('then2: ', res);
}).catch((error) => {
console.log('catch: ', error);
});
/**
Execution sequence and Analysis :
The order :
* 'then1: success1'
* 'then2: undefined'
analysis :
1. Yes resolve('success1') after , Changed the state to resolve, Ignore new Promise hinder
2. Will be the first 1 individual .then() Add to micro task
3. Execution section 1 individual .then(), Will be the first 2 individual .then() Promoting micro tasks
*/
10.2 Topic two
Return directory
const promise = new Promise((resolve, reject) => {
reject('error');
resolve('success2');
});
promise.then((res) => {
console.log('then1: ', res);
}).then((res) => {
console.log('then2: ' ,res);
}).catch((error) => {
console.log('catch: ', error);
}).then((res) => {
console.log('then3: ', res);
})
/**
Execution sequence and Analysis :
The order :
* 'catch: error'
* 'then3: undefined'
analysis :
1. meet new Promise(), take reject('error') perform , change Promise The state of
2. meet .catch(), Push it into micro tasks
3. perform .catch() What's in it , Output 'catch: error', then return Promise {<pending>}
4. Perform the next micro task .then(), Output then3: undefined
*/
10.3 Topic three
Return directory
Promise
.resolve(1)
.then((res) => {
console.log(res);
return 2;
}).catch((err) => {
return 3;
}).then((res) => {
console.log(res);
});
/**
Execution sequence and Analysis :
The order :
* 1
* 2
analysis :
1. resolve(1) The first one .then, Print 1
2. return 2 It's going to be packaged as resolve(2)
3. Because no reject, So don't go .catch
4. Finish the first 2 individual .then, Print 2
*/
10.4 Topic four
Return directory
Promise
.reject(1)
.then((res) => {
console.log(res);
return 2;
}).catch((err) => {
console.log(err);
return 3;
}).then((res) => {
console.log(res);
});
/**
Execution sequence and Analysis :
The order :
* 1
* 3
analysis :
1. reject(1) Will go .catch, So first output 1
2. return 3 It's going to be packaged as resolve(3)
3. So keep going 2 individual .then, Output 3
*/
10.5 Topic 5
Return directory
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('timer');
resolve('success');
}, 0);
});
const start = Date.now();
promise.then((res) => {
console.log(res, Date.now() - start);
});
promise.then((res) => {
console.log(res, Date.now() - start);
});
/**
Execution sequence and Analysis :
The order :
* 'timer'
* 'success 4'
* 'success 4'
notes : Also have 3/4 perhaps 4/5 The situation of
analysis :
1. new Promise take setTimeout Add to macro task
2. After executing the macro task script, And then execute setTimeout
3. Output 'timer'
4. Mark Promise Status as resolve
5. The first one. .then() Put in micro tasks
6. Put the second .then() Put in micro tasks
7. Because of the steps 5 And steps 6 When , Both are the same resolve value , So it's all 'success'
8. Output success 4
9. Output success 4
10. If the execution is slow , Then the values of the two outputs will be inconsistent . for example 3、4
*/
10.6 Topic 6
Return directory
Promise.resolve().then(() => {
return new Error('error!');
}).then((res) => {
console.log('then: ', res);
}).catch((err) => {
console.log('catch: ', err);
});
/**
Execution sequence and Analysis :
The order :
* 'then: Error: error!'
analysis :
return new Error('error!') Will be wrapped up in return Promise.resolve(new Error('error!')) Back to .then()
*/
10.7 Topic 7
Return directory
const promise = Promise.resolve().then(() => {
return promise;
});
promise.catch((err) => {
console.log(err);
});
/**
Execution sequence and Analysis :
The order :
* TypeError: Chaining cycle detected for promise #<Promise>
analysis :
Can't return promise In itself , It's going to create a dead cycle
*/
10.8 Topic 8
Return directory
Promise
.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log);
/**
Execution sequence and Analysis :
The order :
* 1
analysis :
1. .then and .catch The parameter of is expected to be a function , Pass through of values occurs when non functions are passed in
2. Value transmission leads to 1 individual then And the 2 individual then It's not a function , That led it to the last 1 individual then Inside
*/
10.9 Topic nine
Return directory
Promise
.reject('err')
.then((res) => {
console.log('success: ', res);
}, (err) => {
console.log('error: ', err);
}).catch((err) => {
console.log('catch: ', err);
})
/**
Execution sequence and Analysis :
The order :
* 'error: err'
analysis :
reject('err') Will enter Promise.then Second parameter of , So the output 'error: err'
*/
If .then()
No 2 Parameters are removed , Then it will enter .catch()
Function .
10.10 Topic ten
Return directory
Promise
.resolve()
.then((res) => {
throw new Error('error!');
}, (err) => {
console.log('error: ', err);
}).catch((err) => {
console.log('catch: ', err);
})
/**
Execution sequence and Analysis :
The order :
* catch: Error: error!
analysis :
the reason being that .resolve(), So it will execute .then The first 1 Parameters , then return Value to .catch in
Instead of going back to 2 On one parameter
*/
10.11 Topic eleven
Return directory
.finally()
No matter what the method isPromise
The object's final state is executed ..finally()
Method does not accept any parameters , That means you're in.finally()
There is no way to knowPromise
The final state isresolved
stillrejected
Of .- The default it eventually returns will be the last one
Promise
The object is worth , However, if an exception is thrown, the exception is returnedPromise
object .
Promise
.resolve('1')
.then((res) => {
console.log(res);
}).finally(() => {
console.log('finally1');
});
Promise
.resolve('2')
.finally(() => {
console.log('finally2');
return ' Here is finally2';
}).then((res) => {
console.log('finally2 hinder then function ', res);
})
/**
Execution sequence and Analysis :
The order :
* 1
* 'finally2'
* 'finally1'
* 'finally2 hinder then function 2'
analysis :
*/
10.12 Topic twelve
Return directory
Promise
.resolve('1')
.finally(() => {
console.log('finally1');
return new Error(' I am a finally1 Exception thrown in ');
}).then((res) => {
console.log('finally hinder then function : ', res);
}).catch((err) => {
console.log(' Capture the error : ', err);
})
/**
Execution sequence and Analysis :
The order :
* 'finally1'
* Capture the error : Error: I am a finally1 Exception thrown in
analysis :
1. meet resolve('1'), take Promise Change the status of resolve
2. meet .finally(), Into the micro task , Back .then() and .catch() Need to wait .finally() completion of enforcement
3. perform .finally(), Output 'finally1', And then execute throw new Error, This situation will be handed over to .catch()
4. Output Capture the error : Error: I am a finally1 Exception thrown in
Add :
If this is return throw new Error('') What's going to happen ?
It will go .then(), Because it is return In the form of , So as to output :finally hinder then function : 1
Notice the return new Error('') There is no return function , therefore 1 Through
*/
10.13 Topic thirteen
Return directory
function promise1() {
let p = new Promise((resolve) => {
console.log('promise1');
resolve('1');
});
return p;
}
function promise2() {
return new Promise((resolve, reject) => {
reject('error');
});
}
promise1().then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
}).finally(() => {
console.log('finally1');
})
promise2().then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
}).finally(() => {
console.log('finally2');
})
/**
Execution sequence and Analysis :
The order :
* 'promise1'
* '1'
* 'error'
* 'finally1'
* 'finally2'
analysis :
1. perform promise1(), Enter the code inside
2. meet p, take p The content is executed again , Print 'promise1', At the same time, change its status to resolve
3. here promise1() take .then() This micro task advances the micro task queue , We record it as micro 1
4. step 1 To 3,promise1() completion of enforcement
5. Start execution promise2(), meet return new Promise, Change its status to reject
6. meet promise2() Medium .then(), Push it into the micro task queue , Recorded as micro 2
7. script This macro task is finished , Start executing the micro task queue
8. Launch micro 1, Print '1', Because it's from above p yes resolve('1')
9. take promise1() Inside finally1 Push the micro task queue , Recorded as micro 3
10. Launch micro 2, Because when you mark the front , The value of transmission is 'error', So we output 'error'
11. Launch micro 3, Output 'finally1'
12. Launch micro 4, Output 'finally2'
*/
10.14 Topic fourteen
Return directory
function promise1() {
let p = new Promise((resolve) => {
console.log('promise1');
resolve('1');
});
return p;
}
function promise2() {
return new Promise((resolve, reject) => {
reject('error');
});
}
promise1().then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
}).then(() => {
console.log('then1');
})
promise2().then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
}).then(() => {
console.log('then2');
})
/**
Execution sequence and Analysis :
The order :
* 'promise1'
* '1'
* 'error'
* 'then1'
* 'then2'
analysis :
The derivation process is the same as the problem
*/
11、 ... and .all() Relay race
Return directory
Promise Of all
Methods provide the ability to perform asynchronous operations in parallel , And the callback is executed after all asynchronous operations have been executed .
Suppose there's code :
const p = Promise.all([p1, p2, p3]);
p
The status of the p1
、p2
、p3
decision , There are two cases .
- Only
p1
、p2
、p3
The state offulfilled
,p
The state offulfilled
, herep1
、p2
、p3
The return value of consists of an array , Pass top
Callback function for . - as long as
p1
、p2
、p3
One of them wasrejected
,p
The state ofrejected
, At this time, the first wasreject
The return value of the instance of , Will pass top
Callback function for .
therefore , Combine it with setTimeout
As an asynchronous function , Let's try to use .all()
Method :
const one = new Promise((resolve) => {
setTimeout(() => {
console.log('one');
resolve('one');
}, 1000);
})
const two = new Promise((resolve) => {
setTimeout(() => {
console.log('two');
resolve('two');
}, 3000);
})
const three = new Promise((resolve) => {
setTimeout(() => {
console.log('three');
resolve('three');
}, 2000);
})
/*
First, the output :
* one
* three
* two
Then the output res:[ 'one', 'two', 'three' ]
*/
Promise.all([one, two, three]).then((res) => {
console.log(res); // [ 'one', 'two', 'three' ]
});
This is the success of all States , If this 3 There is 1 One is a failure ? Please try it yourself .
Twelve .race() Individual competition
Return directory
and all()
The method is different ,Promise.race()
The method is who goes first and outputs first .
It's like an individual running a race 100 It's like the rice race , Nadi 1 Is worth remembering , Don't pay too much attention to the rest .
In the example above ,.all()
Change it to .race()
, You get different results .
const one = new Promise((resolve) => {
setTimeout(() => {
console.log('one');
resolve('one resolve');
}, 1000);
})
const two = new Promise((resolve) => {
setTimeout(() => {
console.log('two');
resolve('two resolve');
}, 3000);
})
const three = new Promise((resolve) => {
setTimeout(() => {
console.log('three');
resolve('three resolve');
}, 2000);
})
/*
First, the output one
Then the output :one resolve
Finally, output in order :
* three
* two
*/
Promise.race([one, two, three]).then((res) => {
console.log(res); // 'one'
});
13、 ... and Question bank :.all()、.race()
Return directory
Promise.all()
and Promise.race()
usage :
.all()
The function is to receive a set of asynchronous tasks , Then the asynchronous tasks are executed in parallel , And the callback is executed after all asynchronous operations have been executed ..race()
It also receives a set of asynchronous tasks , Then the asynchronous tasks are executed in parallel , Only the result of the first asynchronous operation that completes is reserved , Other methods are still being implemented , But the results will be discarded .
A small summary :
Promise.all().then()
The order of the arrays in the result andPromise.all()
The received arrays are in the same order , Not becausesetTimeout
To change the output of .Promise.all()
andPromise.then()
When an exception is thrown , They'll only throw out the first problem , By.then()
Or the second parameter of.catch()
Capture , But it doesn't affect the execution of other asynchronous tasks in the array .
13.1 Topic 1
Return directory
Let's do it before we do it setTimeout
Review of knowledge points :
setTimeout(() => {
console.log('2');
}, 2000);
setTimeout(() => {
console.log('1-1');
}, 1000);
setTimeout(() => {
console.log('1-2');
}, 1000);
setTimeout(() => {
console.log('0');
}, 0);
What is the output of this piece ?
0 -> 1-1 -> 1-2 -> 2
Convenient memory , We can argue that :
- Both macro tasks , Multiple
setTimeout
, It can be understood as , The ones with less time will be ranked first .
therefore , Originally, our macro task should be a queue , But just like the one on the top script
In macro task , We added 4 individual setTimeout
, And this same kind of setTimeout
, We sort it by time .
Now let's look at the first question :
function runAsync(x) {
const p = new Promise((resolved, reject) => {
if (x % 2 === 0) {
return setTimeout(() => {
console.log(x);
resolved(x);
}, 2000);
}
return setTimeout(() => {
console.log(x);
resolved(x);
}, 1000);
});
return p;
}
Promise.all([
runAsync(1),
runAsync(2),
runAsync(3)
]).then((res) => {
console.log(res);
})
/**
Execution sequence and Analysis :
The order :
* 1
* 3
* 2
* [1, 2, 3]
analysis :
1. Promise.all take 3 individual runAsync Add to the method in order
2. stay script In this macro task , Add... In turn 3 individual setTimeout
3. According to the time in the macro task queue setTimeout Reorder
4. 1、2、3 The corresponding number of seconds is 1s、2s、1s, So the order is 1 -> 3 -> 2
5. Wait a second , Output, respectively, 1、3
6. Wait for two seconds , Output 2
7. perform .then(), according to .all() Output the corresponding array result by sorting the array in ( How to get in and out )
Applicable scenario :
You need to preload multiple images 、 Static files, etc , Can pass Promise.all() To deal with
*/
13.2 Topic two
Return directory
function runAsync (x) {
const p = new Promise((res, rej) => {
if (x === 3) {
return setTimeout(() => {
rej(x, console.log(x));
}, 500);
}
return setTimeout(() => {
res(x, console.log(x));
}, 1000);
});
return p;
}
function runReject (x) {
const p = new Promise((res, rej) => {
return setTimeout(() => {
rej(x, console.log(x));
}, 1000 * x);
});
return p;
}
Promise.all([
runAsync(1),
runReject(4),
runAsync(3),
runReject(2),
]).then((res) => {
console.log('then: ', res);
}, (err) => {
console.log('err: ', err);
}).catch((err) => {
console.log('catch: ', err);
})
/**
Execution sequence and Analysis :
The order :
* 3
* err: 3
* 1
* 2
* 4
analysis :
1. First , We should .all() It's a queue , fifo
2. At this point, the macro task is added in turn setTimeout(1)、setTimeout(4)、setTimeout(3)、setTimeout(2)
3. OK, We said before , identical setTimeout Will be sorted , So the order becomes 3 -> 1 -> 2 -> 4
4. By this time setTimeout The corresponding time is 500ms、1s、2s、4s
5. then , There's something new to remember :.catch Can only capture .all The first exception in it , And only once
6. therefore , Execute first 3 When , It will output 3 -> err: 3
7. hinder 2 and 4 The exception is no longer thrown , Output... In sequence 1 -> 2 -> 4
*/
13.3 Topic three
Return directory
function runAsync(x) {
const p = new Promise((resolved, reject) => {
if (x % 2 === 0) {
return setTimeout(() => {
console.log(x);
resolved(x);
}, 2000);
}
return setTimeout(() => {
console.log(x);
resolved(x);
}, 1000);
});
return p;
}
Promise.race([
runAsync(2),
runAsync(1),
runAsync(3)
]).then((res) => {
console.log('res: ', res);
})
/**
Execution sequence and Analysis :
The order :
* 1
* 'res: 1'
* 3
* 2
Be careful :
Node v10.16.0 The answer is slightly different
analysis :
1. Promise.race() take 3 individual runAsync Add to the method in order
2. stay script In this macro task , Add... In turn 3 individual setTimeout Macro task :2 -> 1 -> 3
3. According to the time in the macro task queue setTimeout Reorder
4. 1、2、3 The corresponding number of seconds is 1s、2s、1s, So the order is 1 -> 3 -> 2
5. Wait a second , Output 1
6. here .race() Can't wait to tell you the result , Follow the output res: 1
7. Followed by output 3
8. Wait for two seconds , Output 2
Applicable scenario :
use race Set timeout for an asynchronous request , And execute corresponding operation after timeout
*/
13.4 Topic four
Return directory
function runAsync (x) {
const p = new Promise((res, rej) => {
if (x === 3) {
return setTimeout(() => {
rej(x, console.log(x));
}, 500);
}
return setTimeout(() => {
res(x, console.log(x));
}, 1000);
});
return p;
}
function runReject (x) {
const p = new Promise((res, rej) => {
return setTimeout(() => {
rej(x, console.log(x));
}, 1000 * x);
});
return p;
}
Promise.race([
runAsync(1),
runReject(4),
runAsync(3),
runReject(2),
]).then((res) => {
console.log('then: ', res);
}, (err) => {
console.log('err: ', err);
}).catch((err) => {
console.log('catch: ', err);
})
/**
Execution sequence and Analysis :
The order :
* 3
* err: 3
* 1
* 2
* 4
analysis :
1. First , We should .race() It's a queue , fifo
2. At this point, the macro task is added in turn setTimeout(1)、setTimeout(4)、setTimeout(3)、setTimeout(2)
3. OK, We said before , identical setTimeout Will be sorted , So the order becomes 3 -> 1 -> 2 -> 4
4. By this time setTimeout The corresponding time is 500ms、1s、2s、4s
5. then , Need to remember a little :.race() Only the one who runs first
6. therefore , Execute first 3 When , It will output 3 -> err: 3
7. hinder 2 and 4 The exception is no longer thrown , Output... In sequence 1 -> 2 -> 4
*/
fourteen Promise Source code
Return directory
stay jsliang Handwritten source code series has a detailed analysis .
15、 ... and Question bank : combination async/await
Return directory
summary :
- stay
function()
Come across itawait
Go straight to the contents . - If
function()
Insideawait
There is more code behind , Think of it asPromise.then()
equally , As a micro task .
15.1 Topic 1
Return directory
async function async1() {
console.log(1);
await async2();
console.log(2);
}
async function async2() {
console.log(3);
}
async1();
console.log(4);
/**
Execution sequence and Analysis :
The order :
* 1
* 3
* 4
* 2
analysis :
1. First , We execute script This macro task
2. meet async1(), Execute the code inside , Output 1
3. meet await async2(), blocked , So it needs to be executed first async2()
4. perform async2(), Output 3
5. meet console.log(4), Output 4
6. The blocking part is gone ,script The macro task is finished , Go on async1() hinder
7. Output 2
*/
15.2 Topic two
Return directory
async function async1() {
console.log('async');
new Promise((resolve) => {
console.log('promise');
resolve();
}).then((res) => {
console.log('promise.then');
})
}
async1();
console.log('start');
/**
Execution sequence and Analysis :
The order :
* 'async'
* 'promise'
* 'start'
* 'promise.then'
analysis :
1. First , We execute script This macro task
2. meet async1(), Execute the code inside , Output 'async'
3. meet new Promise, Execute the code inside , Output 'promise'
4. take Promise The status of is marked as resolved
5. take .then() Into the micro task
6. Output 'start'
7. Perform micro tasks .then(), Output 'promise.then'
*/
15.3 Topic three
Return directory
async function async1() {
console.log('async1 start');
setTimeout(() => {
console.log('timer1 start');
}, 0);
Promise.resolve().then((res) => {
console.log('promise1');
})
await async2();
setTimeout(() => {
console.log('timer1 end');
}, 0);
console.log('async1 end');
}
async function async2() {
setTimeout(() => {
console.log('timer2');
}, 0);
Promise.resolve().then((res) => {
console.log('promise2');
})
console.log('async2');
}
async1();
console.log('start');
/**
Execution sequence and Analysis :
The order :
* 'async1 start'
* 'async2'
* 'start'
* 'promise1'
* 'promise2'
* 'async1 end'
* 'timer1 start'
* 'timer2'
* 'timer1 end'
analysis :
1. First , Let's straighten out the fact that : stay await hinder , It will wait until all the micro tasks in the current macro task are completed , And execute
2. meet async1(), Start executing what's inside
3. Output 'async1 start'
4. take 'timer1 start' Put it in the macro task queue , Mark as macro 1
5. take 'promise1' Into the micro task queue , Marked as micro 1
6. meet await async2(), Execute first async2, Block the following code , The code after the mark is "after the horse" 1
7. perform async2, meet 'timer2', Put it in the macro task queue , Mark as macro 2
8. meet 'promise2', Put it in the micro task queue , Marked as micro 2
9. Output 'async2'
10. async2 Walk the , Keep going down , Output start
11. The current is 3 We didn't leave , The difference is micro 1、 tiny 2 And after the horse 1
12. 【 memorize mechanically 】, Encounter not to go 11 This situation , We need to remember to perform the current micro task first , After a while
13. Perform micro tasks , Output 'promise1'、'promise2'
14. To carry out a post-mortem , take 'timer1 end' Put it in the macro task queue , This is the macro 3
15. Output 'async1 end'
16. Execute the macro in turn 1、 macro 2 and macro 3, Output 'timer1 start' -> 'timer2' -> 'timer1 end'
Soul ascension :
If 'timer1 start' -> 'timer2' -> 'timer1 end' The corresponding time is 500ms、1000ms、500ms, What is the output ?
*/
15.4 Topic four
Return directory
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
setTimeout(() => {
console.log('timer1');
}, 0);
}
async function async2() {
setTimeout(() => {
console.log('timer2');
}, 0);
console.log('async2');
}
async1();
setTimeout(() => {
console.log('timer3');
}, 0);
console.log('start');
/**
Execution sequence and Analysis :
The order :
* 'async1 start'
* 'async2'
* 'start'
* 'async1 end'
* 'timer2'
* 'timer3'
* 'timer1'
analysis :
The idea is the same as above
*/
15.5 Topic 5
Return directory
async function fn() {
return 123;
}
fn().then((res) => {
console.log(res);
})
/**
Execution sequence and Analysis :
The order :
* 123
analysis :
Under normal circumstances , async Medium await The order is a Promise object , Returns the result of the object
But if not Promise Object words , The corresponding value will be returned directly , amount to Promise.resolve();
*/
15.6 Topic 6
Return directory
async function async1() {
console.log('async1 start');
await new Promise((resolve) => {
console.log('promise1');
})
console.log('async1 success');
return 'async1 end';
}
console.log('script start');
async1().then((res) => {
console.log('res: ', res);
})
console.log('script end');
/**
Execution sequence and Analysis :
The order :
* 'script start'
* 'async1 start'
* 'promise1'
* 'script end'
analysis :
1. Special questions
2. stay await hinder Promise There is no return value , therefore await Will be waiting
3. In this case ,async1 success None of the following will be implemented
reflection :
If in 'promise1' Add a line after resolve('123'); What will happen ?
*/
15.7 Topic 7
Return directory
async function async1() {
console.log('async1 start');
await new Promise((resolve) => {
console.log('promise1');
resolve('promise resolve');
})
console.log('async1 success');
return 'async1 end';
}
console.log('script start');
async1().then((res) => {
console.log('res: ', res);
})
new Promise((resolve) => {
console.log('promsie2');
setTimeout(() => {
console.log('timer');
}, 0);
})
/**
Execution sequence and Analysis :
The order :
* 'script start'
* 'async1 start'
* 'promise1'
* 'promsie2'
* 'async1 success'
* 'res: async1 end'
* 'timer'
analysis :
1. Following the analysis of the previous question ,Promise must resolve 了 ,await Later code will continue to execute
2. Take the whole thing first script Macro task , Output 'script start'
3. meet async1() Implementation , Go inside and have a look
4. Output 'async1 start'
5. meet await new Prmise
6. Output 'promise1'
7. notice resolve, change Promise state , inform await There are waiting objects , Throw the rest of the content into the micro task 1
8. Go ahead and do the following new Promsie
9. Output 'promsie2'
10. take setTimeout Throw in the macro task 1
11. Now there's a micro task 1 And a macro task 1
12. Go ahead with micro tasks 1
13. Output 'async1 success'
14. meet return, Tell me to add a micro task after 2
15. Continue to perform micro tasks 2, Output 'res: async1 end'
16. There are no other micro tasks , Macro output task queue , Output 'timer1'
*/
15.8 Topic 8
Return directory
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(() => {
console.log('settimeout');
}, 0);
async1();
new Promise((resolve) => {
console.log('promise1');
resolve();
}).then((res) => {
console.log('promise2');
})
console.log('script end');
/**
Execution sequence and Analysis :
The order :
* 'script start'
* 'async1 start'
* 'async2'
* 'promise1'
* 'script end'
* 'promise2'
* 'async1 end'
* 'settimeout'
analysis :
There's no need to explain here , Similar to the title above
*/
15.9 Topic nine
Return directory
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(() => {
console.log('settimeout');
}, 0);
async1();
new Promise((resolve) => {
console.log('promise1');
resolve();
}).then((res) => {
console.log('promise2');
})
console.log('script end');
/**
Execution sequence and Analysis :
The order :
* 'script start'
* 'async1 start'
* 'async2'
* 'promise1'
* 'script end'
* 'async1 end'
* 'promise2'
* 'settimeout'
Be careful :
The output here is 'async1 end' and 'promise2', stay Node v10.16.0 It's the reverse
analysis :
There's no need to explain here , Similar to the title above
*/
15.10 Topic ten
Return directory
async function testSomething() {
console.log('test something');
return 'test something';
}
async function testAsync() {
console.log('test async');
return Promise.resolve('hello test async');
}
async function test() {
console.log('test start');
const v1 = await testSomething();
console.log('v1: ', v1);
const v2 = await testAsync();
console.log('v2: ', v2);
console.log(v1, v2);
}
test();
const promise = new Promise((resolve) => {
console.log('promise start');
resolve('promise');
})
promise.then((val) => {
console.log(val);
})
console.log('test end');
/**
Execution sequence and Analysis :
The order :
* 'test start'
* 'test something'
* 'promise start'
* 'test end'
* 'v1: test something'
* 'test async'
* 'promise'
* 'v2: hello test async'
* 'test something' 'hello test async'
Be careful :
The output here is Node v10.16.0 Is different
analysis :
There's no need to explain here , Similar to the title above
*/
15.11 Topic eleven
Return directory
Get started async
Deal with wrong questions .
async function async1() {
await async2();
console.log('async1');
return 'async1 success';
}
async function async2() {
return new Promise((resolve, reject) => {
console.log('async2');
reject('error');
})
}
async1().then((res) => {
console.log('res: ', res);
})
/**
Execution sequence and Analysis :
The order :
* 'async2'
* Promise {<rejected>: "error"}
analysis :
If in async Error thrown in function , The error result is terminated , Will not continue down .throw new Error So it is with .
*/
sixteen Comprehensive questions
Return directory
16.1 Topic 1
Return directory
const first = () => (new Promise((resolve1, reject1) => {
console.log(3);
const p = new Promise((resolve2, reject2) => {
console.log(7);
setTimeout(() => {
console.log(5);
resolve1(6);
console.log(p);
}, 0);
resolve2(1);
});
resolve1(2);
p.then((res1) => {
console.log('res1: ', res1);
});
}));
first().then((res2) => {
console.log('res2: ', res2);
});
console.log(4);
/**
Execution order :
* 3
* 7
* 4
* res: 1
* res: 2
* 5
* Promise{ <resolve> 1 }
*/
16.2 Topic two
Return directory
const async1 = async() => {
console.log('async1');
setTimeout(() => {
console.log('timer1');
}, 2000);
await new Promise((resolve) => {
console.log('promise1');
})
console.log('async1 end');
return 'async1 success';
};
console.log('script start');
async1().then((res1) => {
console.log('res1: ', res1);
})
console.log('script end');
Promise
.resolve(1)
.then(2)
.then(Promise.resolve(3))
.catch(4)
.then((res2) => {
console.log('res2: ', res2);
})
setTimeout(() => {
console.log('timer2');
}, 1000);
/**
Execution order :
* 'script start'
* 'async1'
* 'promise1'
* 'script end'
* 'res2: 1'
* 'timer2'
* 'timer1'
*/
16.3 Topic three
Return directory
const p1 = new Promise((resolve) => {
setTimeout(() => {
resolve('resolve3');
console.log('timer1');
}, 0);
resolve('resolve1');
resolve('resolve2');
}).then((res) => {
console.log(res);
setTimeout(() => {
console.log(p1);
}, 1000);
}).finally((res) => {
console.log('finally: ', res);
})
/**
Execution order :
* 'resolve1'
* 'finally: undefined'
* 'timer1'
* 'Promise { <resolved> undefined }'
*/
seventeen Big factory
Return directory
17.1 Use Promise Output every second 1、2、3
Return directory
const oneToThree = () => {
const arr = [1, 2, 3];
arr.reduce((prev, next) => {
return prev.then(() => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(next);
resolve();
}, 1000);
})
});
}, Promise.resolve())
};
console.log(oneToThree());
rewrite forEach:
/**
* Implementation function forEach(arr, cb), send cb Deal with one by one arr The elements in
* A process can be synchronous , It can also be asynchronous
* The current element must be processed before the next one can be processed .
* Tips :cb If the function is executed asynchronously , Will return a Promise
*/
const liangEach = (arr, cb) => {
arr.reduce((prev, next) => {
return prev.then((res1) => {
return cb(next);
});
}, Promise.resolve())
};
const arr = [1, 2, 5];
liangEach(arr, (n) => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(n);
resolve();
}, 1000);
})
})
If there is async/await
Realization :
/**
* Implementation function forEach(arr, cb), send cb Deal with one by one arr The elements in
* A process can be synchronous , It can also be asynchronous
* The current element must be processed before the next one can be processed .
* Tips :cb If the function is executed asynchronously , Will return a Promise
*/
async function liangEach(arr, cb) {
for (let i = 0; i < arr.length; i++) {
await cb(arr[i]);
}
};
const arr = [1, 2, 5];
liangEach(arr, (n) => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(n);
resolve();
}, 1000);
})
});
17.2 Use Promise The traffic lights turn on repeatedly
Return directory
A red light 3 Second light once , Yellow light 2 Second light once , A green light 1 Second light once , use Promise Realization 3 The lights turn on and on again and again .
Known functions :
function red() {
console.log('red');
}
function yellow() {
console.log('yellow');
}
function green() {
console.log('green');
}
answer :
function red() {
console.log('red');
}
function yellow() {
console.log('yellow');
}
function green() {
console.log('green');
}
const light = (timer, cb) => {
return new Promise((resolve) => {
setTimeout(() => {
cb();
resolve();
}, timer);
})
}
const step = () => {
Promise.resolve().then(() => {
return light(3000, red);
}).then(() => {
return light(2000, yellow);
}).then(() => {
return light(1000, green);
}).then(() => {
return step();
})
};
step();
17.3 Realization mergePromise function
Return directory
Realization mergePromise
function , The array passed in is executed in sequence , And put the returned values in the array data
in .
for example :
const time = (timer) => {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, timer)
})
}
const ajax1 = () => time(2000).then(() => {
console.log(1);
return 1
})
const ajax2 = () => time(1000).then(() => {
console.log(2);
return 2
})
const ajax3 = () => time(1000).then(() => {
console.log(3);
return 3
})
function mergePromise () {
// Write the code here
}
mergePromise([ajax1, ajax2, ajax3]).then(data => {
console.log("done");
console.log(data); // data by [1, 2, 3]
});
// Ask to output separately
// 1
// 2
// 3
// done
// [1, 2, 3]
answer :
const time = (timer) => {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, timer)
})
}
const ajax1 = () => time(2000).then(() => {
console.log(1);
return 1
})
const ajax2 = () => time(1000).then(() => {
console.log(2);
return 2
})
const ajax3 = () => time(1000).then(() => {
console.log(3);
return 3
})
function mergePromise (ajaxList) {
const data = [];
let promise = Promise.resolve();
ajaxList.forEach((ajax) => {
promise = promise.then(() => {
return ajax();
}).then((resolve) => {
data.push(resolve);
return data;
})
})
return promise;
}
mergePromise([ajax1, ajax2, ajax3]).then(data => {
console.log("done");
console.log(data); // data by [1, 2, 3]
});
// Ask to output separately
// 1
// 2
// 3
// done
// [1, 2, 3]
17.4 according to PromiseA+ Realize one of your own Promise
Return directory
stay jsliang Handwritten source code series has a detailed analysis .
17.5 Encapsulate a method to load images asynchronously
Return directory
function loadImg(url) {
// ... Implementation code
}
answer :
function loadImg(url) {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
console.log(' Image loading complete ');
resolve(image);
}
image.onerror = () => {
reject(new Error(' Loading failed ' + url));
}
image.src = url;
})
}
17.6 Limit the number of concurrent asynchronous operations and complete them as quickly as possible
Return directory
List of known pictures :
var urls = [
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting1.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting2.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting3.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting4.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting5.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn6.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn7.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn8.png",
];
Known functions :
function loadImg(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = function() {
console.log(" A picture is loaded ");
resolve(img);
};
img.onerror = function() {
reject(new Error('Could not load image at' + url));
};
img.src = url;
});
};
function limitLoad(urls, handler, limit) {
// ... Implementation code
}
Please download at the same time the link proficiency does not exceed 3 In the case of , Finish as soon as possible .
const urls = [
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting1.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting2.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting3.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting4.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting5.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn6.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn7.png",
"https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn8.png",
];
function loadImg(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = function() {
console.log(" A picture is loaded ");
resolve(img);
};
img.onerror = function() {
reject(new Error('Could not load image at' + url));
};
img.src = url;
});
}
function limitLoad(urls, handler, limit) {
let sequence = [].concat(urls); // Copy urls
// This step is to initialize promises This " Containers "
let promises = sequence.splice(0, limit).map((url, index) => {
return handler(url).then(() => {
// The subscript is returned to know which item in the array is completed first
return index;
});
});
// Note that the entire variable procedure is returned here , So you get a Promise, You can chain call it outside
return sequence
.reduce((pCollect, url) => {
return pCollect
.then(() => {
return Promise.race(promises); // Returns the completed subscript
})
.then((fastestIndex) => {
// Get the completed subscript
// take " Containers " The replacement that has been completed in
promises[fastestIndex] = handler(url).then(() => {
return fastestIndex; // To continue to return the subscript to , So that the next variable
});
})
.catch((err) => {
console.error(err);
});
}, Promise.resolve()) // Initialize incoming
.then(() => {
// The last three use .all To call
return Promise.all(promises);
});
}
limitLoad(urls, loadImg, 3)
.then((res) => {
console.log(" All the pictures are loaded ");
console.log(res);
})
.catch((err) => {
console.error(err);
});
17.7 JS Implement asynchronous scheduler
Return directory
Review the question and complete the following code :
/**
* subject :JS Implement asynchronous scheduler
* requirement :
* JS Implement an asynchronous scheduler with concurrency constraints Scheduler, The maximum number of tasks guaranteed to run simultaneously is 2 individual
* Perfect the following code Scheduler class , Make the program output correctly
*/
class Scheduler {
add(promiseCreator) {
// ...
}
// ...
}
const timeout = (time) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, time);
});
};
const scheduler = new Scheduler();
const addTack = (time, order) => {
return scheduler
.add(() => timeout(time))
.then(() => console.log(order));
};
addTack(1000, '1');
addTack(500, '2');
addTack(300, '3');
addTack(400, '4');
// Output :2 3 1 4
// In limine ,1、2 Two tasks enter the queue
// 500ms when , complete 2, Output 2, Mission 3 Enter the team
// 800ms when , complete 3, Output 3, Mission 4 Enter the team
// 1000ms when , complete 1, Output 1, There's no one in the team
// 1200ms when , complete 4, Output 4, There's no one in the team
// Team entry complete , Output 2 3 1 4
Realization way (async/await
):
/**
* subject :JS Implement asynchronous scheduler
* requirement :
* JS Implement an asynchronous scheduler with concurrency constraints Scheduler, The maximum number of tasks guaranteed to run simultaneously is 2 individual
* Perfect the following code Scheduler class , Make the program output correctly
*/
class Scheduler {
constructor(maxNum) {
this.taskList = [];
this.count = 0;
this.maxNum = maxNum; // Maximum number of concurrent
}
async add(promiseCreator) {
// If the current concurrency exceeds the maximum concurrency , Then enter the task queue and wait
if (this.count >= this.maxNum) {
await new Promise((resolve) => {
this.taskList.push(resolve);
})
}
// frequency + 1( If the previous one is not finished , Then keep adding )
this.count++;
// Wait for the content to be executed
const result = await promiseCreator();
// frequency - 1
this.count--;
// Get the team out of the team first
if (this.taskList.length) {
this.taskList.shift()();
}
// call chaining , Return the result value
return result;
}
}
const timeout = (time) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, time);
});
};
const scheduler = new Scheduler(2);
const addTack = (time, order) => {
return scheduler
.add(() => timeout(time))
.then(() => console.log(order));
};
addTack(1000, '1');
addTack(500, '2');
addTack(300, '3');
addTack(400, '4');
// Output :2 3 1 4
// In limine ,1、2 Two tasks enter the queue
// 500ms when , complete 2, Output 2, Mission 3 Enter the team
// 800ms when , complete 3, Output 3, Mission 4 Enter the team
// 1000ms when , complete 1, Output 1, There's no one in the team
// 1200ms when , complete 4, Output 4, There's no one in the team
// Team entry complete , Output 2 3 1 4
eighteen summary
Return directory
Write here , Finally, I've finished all the content .
First , Most of the titles of this article , Taken from the LinDaiDai_ Lin is stupefied The article , Thank you very much for his article , I spent it. 8 hours , Combine these topics with browsers and Node
The print of the , Finally, we have a rough idea of this related content .
meanwhile , During the period of jobless vagrant , Appreciate the dull encouragement , Be confident in your job search .
then , This article is probably Promise
It's a letter of persuasion !
Because according to the estimates I compiled and collated , It takes about a week to read and master !
however , If you really finish watching , So congratulations :Promise
You have already got through the two channels of Ren Du .
Last , If your partner thinks the article is good , All kinds of encouragement are welcome ( give the thumbs-up 、Star……), Contact information can be personal Github home page , If you have any questions, please try to chat in private , After all, sometimes I really feel that time is not enough :
that , I'll see you later !
jsliang The document library of is made up of Liang Junrong use Knowledge sharing A signature - Noncommercial use - Share in the same way 4.0 The international license agreement Licensing .<br/> be based on https://github.com/LiangJunrong/document-library Creation of works on .<br/> Use rights other than those authorized by this license agreement can be obtained from https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ To obtain .