Hello everyone, I am Lin Yiyi, asynchronous programming in JS is inevitable, but also interview must ask. In this article, asynchronous programming principles are explained in an easy-to-understand language. Get started at 😁
Mind mapping
I. Timer
Timer: Set a timer. When the timer is set, the browser will execute the corresponding method. After each timer is executed, a number is returned. The number of each timer is different.
1. Set the timer
- setTimeout([function], [interval])
Function is executed after the specified time is reached. And execute it once
let count = 1
let timer = setTimeout(function(){
count++
console.log(count) / / 2
}, 1000)
console.log(timer) / / 1
Copy the code
- setInterval([function], [interval])
In the set time to execute, do not actively stop the case has been executed.
let count = 1
let timer = setInterval(function(){
count++
console.log(count) / / 2
}, 1000)
console.log(timer) / / 1
/* * 2 * 3 * 4 *... * /
Copy the code
2. Clear the timer
ClearTimeout/clearInterval both can clear the above two kinds of timers.
- How do I clear timers?
You only need to clear the return value number of the timer.
let count = 1
let timer = setInterval(function(){
count++
console.log(count)
// count == 3 ? clearTimeout(timer) : null
count == 3 ? clearInterval(timer) : null
}, 1000)
Copy the code
Second, the principle of asynchronous programming
Let’s start with a little example
let a = 0
setTimeout(() = >{
console.log('a', ++a)
}, 0)
console.log(a)
/* Outputs * 0 * 1 */
Copy the code
In the example above, setTimeout is asynchronous. The browser will queue the asynchronous code and wait until the synchronous code completes
1. The synchronous
JS is single-threaded. When the code is executed from top to bottom, the synchronized code needs to be executed before the next task can be carried out. So cycles and things like that
2. The asynchronous
All tasks that need to wait are asynchronous. When asynchronous code is encountered, instead of waiting, the asynchronous task is directly put into the task queue, and the code that is not asynchronous is returned to execute after the subsequent task completes. Such as event binding, all timers, asynchronous processing of Ajax, partial callback functions, browser rendering, etc.
let a = 0
setTimeout(() = >{
console.log('a', ++a)
}, 0)
console.log(a)
while(true){
}
Copy the code
The code above is in an infinite loop and will not execute even when the timer is up. Because synchronized code does not execute until it has completed one step.
Third, the promise
1. Basic concepts
Promise is just a class that manages asynchronous programming and is itself synchronous. There are three state pending/Promise fulfilled/rejected, only two states appear in three state either success or failure. The executor callback must be passed in when new Promise() or an error is reported. There are two arguments in the callback: resolve, reject.
pending
: initializes the state and starts executing asynchronous tasks.new Promise(()=>{})
“And the promise state will becomepending
fulfilled
: Indicates that the command is successfulresolve()
.rejected
: Failed and executedrejected()
.
Let’s start with a little chestnut.
new Promise(() = > {
setTimeout(() = > {
console.log(1)},0)
console.log(2)
}).then()
console.log(3)
/* Outputs * 2 * 3 * 1 */
Copy the code
To create a new Promise instance is new to this process would function to perform first Promise (don’t know the new instance is created in the process of what happened can look at this interview | you have to know the JS prototype and prototype chain). Functions with asynchronous operations will be added to the task queue until the synchronous execution is complete, such as setTimeout function in the function. So the output is 2,3,1.
Let’s look at a little chestnut
const promise = new Promise((resolve, reject) = > {
resolve('success1')
reject('error')
resolve('success2')
})
promise.then((res) = > {
console.log('then: ', res)
}).catch((err) = > {
console.log('catch: ', err)
}
// then: success1
Copy the code
The state of promise can only change once. The final state is either a pity or rejected. This means that resolve()/ reject() in the same promise can only be executed once.
How does Promise manage asynchrony
The promise parameter’s callback body accepts two arguments, resolve/ reject, that can be used as two callback functions.
resolve()
: If the asynchronous operation is executed successfully, the state of the promise becomesfulfilled
, can provide a return value in.then()
The first parameter is receivedreject()
: After the asynchronous operation fails to execute, the state of the promise becomesrejected
, can provide a return value in.then()
The second parameter is receivedOnly one argument is passed in resolve() and reject(). Promise status changes and never changes again. Resolve () and reject() are asynchronous operations. Resolve () and reject() are asynchronous operations that execute the resolve/reject code and wait until the main task is empty to execute the stored method. Promise objects have private properties promise.resolve ()/ promise.reject (), etc.
What about a little chestnut that doesn’t make any sense
new Promise((resolve, reject) = > {
setTimeout(() = > {
console.log('darling')
resolve('ok')
// reject('fail')
console.log('one')},0)
}).then( res= > {
console.log('status:', res)
}, res= > {
console.log('status:', res)
})
/ / Lin
/ / one by one
// ok
Copy the code
Resolve /reject is asynchronous.
3. promise.then(onfulfilled, onrejected) / promise.catch()
promise.then(onfulfilled, onrejected)
promise.then()
The method has two parameters that correspond to two different states of the Promise,fulfilled, rejected
. The corresponding state executes the corresponding method.promise.then()
The argument is a function. If you pass something other than a functionValue through
, that is,resolve()/reject()
The return value of.then()
In receiving.promise.then()
Chaining calls, the reason why chaining calls is not.then()
Methods ofreturn this
But every one of them.then()
Method returns a new onePromise
Instance.
promise.catch()
promise.catch()
是promise.then()
Shorthand for the second parameter, which is used to capturereject()
After the executionrejected
State..catch()
It is also possible to implement chain calls, causes and.then()
The same method returns a new onepromise
.
.then()/.catch()
None of the return values inpromise
Its own instance, because it creates an endless loop
Warm up the topic
1. Give me a small chestnut
Promise.resolve(1)
.then((res) = > {
console.log(res)
return 2
}).catch(err= > {
console.log(err)
}).then( res= > {
console.log(res)
})
/ / 1. 2
Copy the code
The final output is 1, 2,
2. Pick a small chestnut with a value of penetration
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
/ / equivalent to the
// Promise.resolve(1)
// .then(console.log)
Copy the code
3. Then ()/.catch() does not return its own promise instance
let pro = Promise.resolve()
.then(() = > {
console.log('promise', pro)
return pro
})
// Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>
Copy the code
The created Promise instance is Pro, and the return value cannot be Pro, otherwise it will cause an endless loop.
4. About Promise. The catch ()
Let’s start with an interview question
new Promise((resolve, reject) = > {
reject(1)
}).catch(() = > {
console.log(2)
// throw 'err'
}).then(() = > console.log(3), (v) = > console.log(v))
// Output: 2, 3
Copy the code
I don’t know if you got that right
- Catch is indeed the syntactic sugar for the second argument to.then. It is worth mentioning in the
.catch
Internally if no error or a false promise is raisedreject()
The result value returned by.catch isresolve()
All will be displayed as successful. Output The second output is 3.
5. Promise.all([promise1, promise2…] )
Promise.all() waits for all the Promise states in the argument to succeed before executing the callback. Then (), and.catch() if one of them fails. The arguments received are an array of Promise instances, and the.all() method returns a new Promise instance.
- All callbacks were successfully executed
.then()
You get an array - If any of them fail to execute
promise
State, callback.catch
Will catch an execution failurepromise
. - A failed promise causes the promise.all method to stop execution immediately.
var p1 = Promise.resolve(1)
var p2 = Promise.resolve(2)
var p3 = Promise.resolve(3)
let pro = Promise.all([p1, p2, p3])
.then(res= > {
console.log(res) // [1, 2, 3]
})
.catch( err= > {
console.log(err)
})
console.log(pro) // Promise {<pending>}
Copy the code
Then () returns an array of the return values of resolve().
6. Promise.race()
.race() also receives a set of asynchronous tasks and executes them in parallel, keeping only the results of the fastest completed asynchronous operation. The other methods are still running, but the results are discarded.
- It receives an array and only gets the fastest one
resolve()/rejected()
Is not an array
var p1 = new Promise(function(resolve, reject) {
setTimeout(reject, 500."one");
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100."two");
});
Promise.race([p1, p2]).then(function(value) {
console.log(value); // "two"
});
Copy the code
Both are done, but P2 is faster
7. Promise.finally()
The.finally method also returns a Promise, and when the Promise ends, the callback will be executed, whether resolved or Rejected.
let promise = new Promise((resolve, reject) = > {
reject('error')
}).then( res= > {
console.log('then', res)
return res
}).catch( err= > {
console.log('catch', err) // `catch error`
return err
}).finally( () = > {
console.log('finally') //'finally'
})
Copy the code
Warm up the topic
Warm up the topic 1
const promise = new Promise((resolve, reject) = > {
console.log(1)
resolve()
console.log(2)
})
promise.then(() = > {
console.log(3)})console.log(4)
// 1, 2, 4, 3
Copy the code
This is a big pity. Because resolve() is asynchronous, promise.then is also asynchronous, and will not be fulfilled until the fulfilled state of resolve() is fulfilled.
Warm-up questions 2
const promise = new Promise((resolve, reject) = > {
setTimeout(() = > {
console.log('once')
resolve('success')},1000)})const start = Date.now()
promise.then((res) = > {
console.log(res, Date.now() - start)
})
promise.then((res) = > {
console.log(res, Date.now() - start)
})
/* Once * success 1002 * SUCCESS 1002 */
Copy the code
Promise.then () even if there are more than one, the resolve()/reject() calls are executed simultaneously. So success 1002 is also printed
Warm up 3
const p = function(){
return new Promise((resolve, reject) = >{
const p1 = new Promise((resolve, reject) = > {
setTimeout(() = >{
resolve(1)},0)
resolve(2)
})
p1.then((res) = >{
console.log(res)
})
console.log(3)
resolve(4)
})
}
p().then(res= > {
console.log(res)
})
console.log('end')
// 3, end, 2, 4
Copy the code
Resolve (2); resolve(4)·; The result of resolve(1) ‘will not be executed because the Promise state has changed.
Async and await
Let’s start with a chestnut
function fn(){
return new Promise((resolve, reject) = > {
setTimeout( () = > {
Math.random() < 0.5 ? resolve('resolve 001') : reject('reject 002')},0)})}async function get() {
let res = await fn()
console.log(res)
console.log(1212)
}
get()
Copy the code
1. async
async
和await
It was added in ES7promise
The way to do this is with the syntax sugar provided by the ES7 series,await
It cannot be used alone but must be combinedasync
To use.async
Will return apromise
Object,async
Function calls do not block code
2. await
await
Is used toWait to get
apromise
的resolve/reject
The result of the execution, as abovelet res = await fn()
Is the firstfn()
After execution, to obtainresolve/reject
Returns the result, howeverawait
You don’t have to follow onepromise
But it doesn’t make sense.Await or await fn ()
This operation is not synchronous, but asynchronous.await
The following code does not execute, but moves to the task queue waiting area until other tasks in the main stack complete andfn()
In thepromise
Return the result,await
The following code can then be executed back on the main stack.await
You can makepromise
Is more like synchronized code.- if
await
Waiting for thePromise
Return value if yesrejected/peding
.await
None of the following code will execute,reject()
The returned representative has reported an error. Remember that await 10 is equivalent to await promise.resolve (10)
To give an example, async/await is syntactic sugar
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
// The above code is equivalent to ==>
async function async1() {
console.log('async1 start');
Promise.resolve(async2()).then(() = > {
console.log('async1 end')})}Copy the code
thinking
Warm-up 1, is await synchronous? And find the output result
console.log(1)
function fn(){
return new Promise((resolve, reject) = > {
console.log(5)
resolve('resolve 001')
console.log(6)})}async function get() {
console.log(2)
let res = await fn()
console.log(res)
console.log(3)
}
get()
console.log(4)
//1, 2, 5, 6, 4, resolve 001, 3
Copy the code
After fn() is executed, the thread will begin to relinquish. Then the code below the “await” will not execute immediately and will go to the waiting area of the main stack. After console.log(4) is executed in the main stack, the code at the “await” will be executed.
2. Warm-up 2, find the output result
console.log(1)
async function get() {
console.log(2)
let res = await 200
console.log(res)
console.log(3)
}
get()
console.log(4)
// 1, 2, 4, 200, 3
Copy the code
A. await b. await C. await D. await It also states that await can be followed by a non-promise instance.
3. Warm up and find the output
async function fn(){
await fo() // Promise.resolve(fo()) ==> undefined
console.log(1)}async function fo(){
}
fn()
/ / 1
Copy the code
The output is 1 because fo() has a return value, which is not reject()
4. Warm up and find the output
async function async1() {
console.log('async1 start')
await new Promise(resolve= > {
console.log('promise1')})console.log('async1 success')
return 'async1 end'
}
console.log('srcipt start')
async1().then(res= > console.log(res))
console.log('srcipt end')
// srcipt start, async1 start, promise1, srcipt end,
Copy the code
Async1 success is not output above because the Promise instance returned by await is still pending and no result is returned so the following code will not execute. Async1 returns a Promise and does not print async1 end
4. Classic interview questions
1. Advantages and disadvantages of Promises/Why use promises?
- Pros: Promise solves callback hell, promise greatly enhances the readability and maintainability of nested functions,
- Cons: Promise can’t be cancelled, errors need to be caught with callback functions; If no callback function is set, errors thrown from within a Promise are not reflected externally. When you are in the pending state, you cannot tell what stage of progress you are at, whether you have just started or are about to complete
2. Differences between setTimeout, Promise, Async/Await
- SetTimeout: The setTimeout callback is placed in the macro task queue until the execution stack is empty
- Promise: Promise itself is a synchronous execute now function. When resolve or reject is executed in executor, then/catch is executed asynchronously. When the main stack is complete, The resolve/reject method is called.
- Async: An async function returns a Promise object. When the function executes, it will return an await and wait until the async operation is completed before executing the following statement in the function body. It can be understood as giving up the thread, out of the async function body.
3. Implementing a sleep function, such as sleep(1000) means waiting for 1000 milliseconds.
function sleep1(time) {
return new Promise(resolve= > {
setTimeout(() = > {
resolve();
}, time);
})
}
sleep1(1000).then(() = > console.log("sleep1"));
Copy the code
4. If the Promise constructor executes synchronously or asynchronously, what about the then method
Promise is synchronous; the callback function is executed immediately when new Promise (callback) is executed, and the then() method is asynchronous.
const promise = new Promise((resolve, reject) = > {
console.log(1)
resolve()
console.log(2)
})
promise.then(() = > {
console.log(3)})console.log(4)
Copy the code
1243, the Promise constructor is executed synchronously and the THEN method asynchronously
5. Introduce the use, principle and error handling of Promise.all
const p = Promise.all([p1, p2, p3]);
Copy the code
The promise. all method takes an array of parameters. P1, P2, and p3 are all Promise instances. (The promise. all method can take arguments that are not arrays, but must have an Iterator interface and return each member as a Promise instance.)
5. Introduce the difference between promise.all, promise.race ()
Look at the introduction above
The various API implementations of Promise will be implemented in the next article. Give a look 😂
Five, the reference
I Promise I will (10 questions)
Classic INTERVIEW Questions: The most detailed handwritten Promise tutorial ever
MDN async/await
Sixth, the end
Thank you for reading here, if the article can enlighten or help you a little welcomegithub starThis is Lin Yiyi. See you next time.