The previous article mainly talked about synchronization and asynchronousness, the 'execution stack', 'message queue', as well as 'macro tasks' and 'micro tasks' derived from each of them. If you understand these concepts If you don’t know much about it, you can go to this link:
https://www.jianshu.com/p/61e7844e68d8
Both macro tasks and micro tasks are asynchronous, including ajax requests and timing. We have a preliminary understanding of promise and know that it is a way to solve asynchronous problems. So what are the methods we commonly use?
Because it involves a lot of knowledge points, this article Mainly let’s talk about callback functions and promises:
1. Callback function
先上代码: function f2() { console.log('2222') } function f1(callback){ console.log('111') setTimeout(function () { callback(); }, 5000); console.log('3333') } f1(f2); 先看下打印值是: 111 3333 五秒后2222
is equivalent to the fact that after the main thread has finished executing, the f2 function will be called through the callback function. This Nothing wrong with it. But look at the following example:
现在我们读取一个文件,fileReader就是一个异步请求 // 这个异步请求就是通过回调函数的方式获取的 var reader = new FileReader() var file = input.files[0] reader.readAsText(file, 'utf-8',function(err, data){ if(err){ console.log(err) } else { console.log(data) } })
It looks very good now, but if there is an error in file upload, we still have to make a judgment in the callback. If we finish reading this file, we have to read multiple Where are the files? Should it be written like this:
读取完文件1之后再接着读取文件2、3 var reader = new FileReader() var file = input.files[0] reader.readAsText(file1, 'utf-8',function(err1, data1){ if(err1){ console.log(err1) } else { console.log(data1) } reader.readAsText(file2, 'utf-8',function(err2, data2){ if(err2){ console.log(err2) } else { console.log(data2) } reader.readAsText(file3, 'utf-8',function(err3, data3){ if(err3){ console.log(err3) } else { console.log(data3) } }) }) })
Writing this way can achieve the requirements, but the readability of this code is relatively poor and it does not look so elegant, which is what we often call 'callback hell'. So how to crack this nested callback? ES6 provides us with promises:
2. Promise
First, let’s understand what a promise is literally? Promise can be translated into commitment and guarantee. You can understand this place as:
My girlfriend asked me to do something. Although I haven’t finished it yet, I promise that there will be a result for you. Success (fulfiled) or failure (rejected), and a waiting state (pending).
还是先上例子 let promise = new Promise((resolve, reject) => { setTimeout(() => { resolve(2000) // 成功以后这个resolve会把成功的结果捕捉到 // reject(2000) // 失败以后这个reject会把失败的结果捕捉到 }, 1000) console.log(1111) }) promise.then(res => { console.log(res) // then里面第一个参数就能拿到捕捉到的成功结果 }, err =>{ console.log(res)// then里面第二个参数就能拿到捕捉到的失败结果 }) 打印结果: 1111 2000(一秒以后)
1. Then chain operation
The then method of the Promise object returns a new Promise object, so the then method can be called through the chain.
Thethen method receives two functions as parameters. The first parameter is the callback when Promise is executed successfully, and the second parameter is the callback when Promise fails to execute. The above example makes it very clear. The two parameters capture the failed callback.
Only one of the two functions will be called. How to understand this sentence?
Your girlfriend asks you to make tomato and egg soup. You either do it or you don’t and order takeout. There is definitely no third option.
The return value of the function will be used to create the Promise object returned by then. How should this sentence be understood? Still the above example:
let promise = new Promise((resolve, reject) => { setTimeout(() => { resolve(2000) }, 1000) console.log(1111) }) promise.then(res => { console.log(res) // 这个地方会打印捕捉到的2000 return res + 1000 // 这个函数的返回值,返回的就是这个promise对象捕捉到的成功的值 }).then(res => { console.log(res) //这个地方打印的就是上一个promise对象return的值 }) 所以打印顺序应该是: 1111 2000 3000
Just now we saw that then accepts two parameters, one is a successful callback and the other is a failed callback. It doesn’t seem that elegant. In addition to then, promise also provides a catch method. :
2. Catch capture operation
This catch is specifically designed to capture error callbacks. Let’s look at the example first:
let promise = new Promise((resolve, reject) => { setTimeout(() => { reject(2000) // 失败以后这个reject会把失败的结果捕捉到 }, 1000) console.log(1111) }) promise.catch(res => { console.log(res) // catch里面就能拿到捕捉到的失败结果 }) 打印结果: 1111 2000(一秒以后)
In addition to then and catch, promise also has We also use the two syntaxes, all and race, briefly:
3, all
Now we have such a requirement. There are three interfaces A, B, and C. Three are required. After all interfaces are successful, the fourth request can be initiated. How to implement it?
Chained calls
let getInfoA = new Promise((resolve, reject) => { console.log('小A开始执行了') resolve() }).then(res => { let getInfoB = new Promise((resolve, reject) => { console.log('小B开始执行了') resolve() }).then(res => { let getInfoC = new Promise((resolve, reject) => { console.log('小C开始执行了') resolve() }).then(res => { console.log('全都执行完了!') }) }) })
It’s one layer inside another, it doesn’t seem so elegant
all
let getInfoA = new Promise((resolve, reject) => { console.log('小A开始执行了') resolve() }) let getInfoB = new Promise((resolve, reject) => { console.log('小B开始执行了') resolve() }) let getInfoC = new Promise((resolve, reject) => { console.log('小C开始执行了') resolve() }) Promise.all([getInfoA, getInfoB, getInfoC]).then(res => { console.log('全都执行完了!') })
Receives an array composed of Promise objects as parameters , when the status of all Promise objects in this array becomes resolved or rejected, it will call the then method. So perfect, so elegant.
4, race
Now there is another requirement, which is also interface A, B, C. As long as one of them responds, I can adjust interface D. So how to implement it?
1. Traditional method
let getInfoA = new Promise((resolve, reject) => { console.log('小A开始执行了') setTimeout((err => { resolve('小A最快') }),1000) }).then(res =>{ console.log(res) }) let getInfoB = new Promise((resolve, reject) => { console.log('小B开始执行了') setTimeout((err => { resolve('小B最快') }),1001) }).then(res =>{ console.log(res) }) let getInfoC = new Promise((resolve, reject) => { console.log('小C开始执行了') setTimeout((err => { resolve('小C最快') }),1002) }).then(res =>{ console.log(res) }) 打印结果 小A开始执行了 小B开始执行了 小C开始执行了 小A最快
This method has to be written three times, and it doesn’t seem to be that elegant. Let’s take a look at how to write race?
2, race
let getInfoA = new Promise((resolve, reject) => { console.log('小A开始执行了') setTimeout((err => { resolve('小A最快') }),1000) }) let getInfoB = new Promise((resolve, reject) => { console.log('小B开始执行了') setTimeout((err => { resolve('小B最快') }),1001) }) let getInfoC = new Promise((resolve, reject) => { console.log('小C开始执行了') setTimeout((err => { resolve('小C最快') }),1002) }) Promise.race([getInfoA, getInfoB, getInfoC]).then(res => { console.log(res) }) 打印结果 小A开始执行了 小B开始执行了 小C开始执行了 小A最快
Similar to Promise.all, Promise.race takes an array composed of Promise objects as parameters. The difference is that as long as one of the Promise objects in the array When the Promsie status changes to resolved or rejected, the .then method can be called.
Promise is a method used by ES6 to solve asynchronous problems. It is now widely used. For example, axios, which we often use, is encapsulated with promise and is very convenient to use.
In addition to promises, ES6 also provides us with the ultimate tricks async and await. Because these two knowledge blocks are relatively large, we are going to talk about them in the next article.
Personal WeChat public account: If Jerry has something to say, he usually posts some technical articles and reading notes. Welcome to communicate.
Recommended tutorial: "JS Tutorial"
The above is the detailed content of Understand promise, async, await. For more information, please follow other related articles on the PHP Chinese website!