First talk about the usage of async , which is put before the function as a keyword to indicate that the function is an asynchronous function, because async means asynchronous, and asynchronous function means that the execution of the function will not block the code behind Implementation. Write an async function
async function timeout() {
return 'hello world';
}
The syntax is very simple, just add the async keyword in front of the function to indicate that it is asynchronous, then how to call it? The async function is also a function. We usually use it as we use the function, just add parentheses to call it, in order to show that it does not block the execution of the code behind it, we add a sentence console.log after the async function call;
async function timeout() {
return 'hello world'
}
timeout();
console.log('虽然在后面,但是我先执行');
Open the browser console and we see
The async function timeout is called, but there is no output. Shouldn't it return'hello world', don't worry, take a look at what timeout() returns? Change the above timeout() statement to console.log(timeout())
async function timeout() {
return 'hello world'
}
console.log(timeout());
console.log('虽然在后面,但是我先执行');
Continue to look at the console
It turns out that the async function returns a promise object. If we want to get the promise return value, we should use the then method and continue to modify the code
async function timeout() {
return 'hello world'
}
timeout().then(result => {
console.log(result);
})
console.log('虽然在后面,但是我先执行');
Look at the console
We got "hello world", and the execution of timeout did not block the execution of the code behind, which is consistent with what we just said.
At this time, you may notice that the Promise in the console has a resolved, which is the internal implementation principle of the async function. If a value is returned in the async function, when the function is called, the Promise.solve() method will be called internally to convert it into a promise object as a return, but what if the timeout function throws an error? Then it will call Promise.reject() to return a promise object, then modify the timeout function
async function timeout(flag) {
if (flag) {
return 'hello world'
} else {
throw 'my god, failure'
}
}
console.log(timeout(true)) // 调用Promise.resolve() 返回promise 对象。
console.log(timeout(false)); // 调用Promise.reject() 返回promise 对象。
The console is as follows:
If an error is thrown inside the function, the promise object has a catch method to catch it.
timeout(false).catch(err => {
console.log(err)
})
The async keyword is almost there. Let’s consider the await keyword again. Await means waiting. So what does it wait for, and what does it follow? In fact, any expression can be put after it, but we are more to put an expression that returns a promise object. Note that the await keyword can only be placed in the async function
Now write a function to return the promise object. The function of this function is to multiply the value by 2 after 2s
// 2s 之后返回双倍的值
function doubleAfter2seconds(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2 * num)
}, 2000);
} )
}
Now write another async function, so that you can use the await keyword. After await is placed an expression that returns the promise object, so it can be followed by a call to the doubleAfter2seconds function.
async function testResult() {
let result = await doubleAfter2seconds(30);
console.log(result);
}
Now call the testResult function
testResult();
Open the console, after 2s, 60 is output.
Now we look at the execution process of the code and call the testResult function. It encounters await in it, await means to wait, the code will stop here and no longer execute downwards. What is it waiting for? After the subsequent promise object is executed, it gets the promise resolve value and returns it. After the return value is obtained, it continues to execute downward. Specific to our code, after encountering await, the code pauses execution, waiting for doubleAfter2seconds(30) to finish executing, and the promise returned by doubleAfter2seconds(30) starts to execute. After 2 seconds, the promise resolves, and the return value is 60. At this time, await gets the return value of 60, and then assigns it to result. After the pause is over, the code starts to execute and executes the console.log statement.
With this function, we may not see the effect of async/await. What if we want to calculate the value of 3 numbers and then output the obtained value?
async function testResult() {
let first = await doubleAfter2seconds(30);
let second = await doubleAfter2seconds(50);
let third = await doubleAfter2seconds(30);
console.log(first + second + third);
}
After 6 seconds, the console output 220, we can see that writing asynchronous code is like writing synchronous code, and there is no callback area anymore.
To write another real example, I used to do a small function, call charge recharge. When the user enters a phone number, first look up the province and city where the phone number is located, and then find the face value that may be recharged according to the province and city. exhibit.
In order to simulate the back-end interface, we create a new node project. Create a new folder async, then npm init -y to create a new package.json file, npm install express --save to install the back-end dependencies, and then create a new server.js file as the server code, and the public folder as the location for static files. Put the index.html file in the public folder, the entire directory is as follows
The server.js file is as follows, to build the simplest web server
const express = require('express');
const app = express();// express.static 提供静态文件,就是html, css, js 文件
app.use(express.static('public'));
app.listen(3000, () => {
console.log('server start');
})
Then write the index.html file. Here I used vue to build the page, and used axios to send ajax requests. For simplicity, I used cdn to introduce them. The html part is very simple, an input box allows users to enter their mobile phone number, a display area for the recharge amount, and the js part, which builds a template according to the requirements of vue
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Async/await</title>
<!-- CDN 引入vue 和 axios -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<!-- 输入框区域 -->
<div style="height:50px">
<input type="text" placeholder="请输入电话号码" v-model="phoneNum">
<button @click="getFaceResult">确定</button>
</div>
<!-- 充值面值 显示区域 -->
<div>
充值面值:
<span v-for="item in faceList" :key='item'>
{{item}}
</span>
</div>
</div>
<!-- js 代码区域 -->
<script>
new Vue({
el: '#app',
data: {
phoneNum: '12345',
faceList: ["20元", "30元", "50元"]
},
methods: {
getFaceResult() {
}
}
})
</script>
</body>
</html>
In order to get the phone number entered by the user, add the v-model command to the input box and bind the phoneNum variable. The display area is bound to the faceList array and displayed by the v-for command. At this time, the command line nodemon server starts the server. If you don't have nodemon installed, you can install it with npm install -g nodemon. After the startup is successful, enter http://localhost:3000, in the browser, you can see the page is as follows, the display is correct
Now we come to dynamically get the recharge face value. When clicking the OK button, we first need to get the province and city based on the phone number, so we write a method to send a request to get the province and city. The method is named getLocation, which accepts a parameter phoneNum, and the background interface is named phoneLocation. When the city location is obtained In the future, we will send a request to get the recharge face value, so we need to write another method getFaceList, which accepts two parameters, province and city, and the background interface is faceList. Add these two methods getLocation, getFaceList under methods
methods: {
//获取到城市信息
getLocation(phoneNum) {
return axios.post('phoneLocation', {
phoneNum
})
},
// 获取面值
getFaceList(province, city) {
return axios.post('/faceList', {
province,
city
})
},
// 点击确定按钮时,获取面值列表
getFaceResult () {
}
}
Now write the two back-end interfaces again. For the sake of demonstration, the writing is very simple, without any verification, just return the data needed by the front-end. Express writing this simple interface is very convenient, add the following code between app.use and app.listen
// 电话号码返回省和市,为了模拟延迟,使用了setTimeout
app.post('/phoneLocation', (req, res) => {
setTimeout(() => {
res.json({
success: true,
obj: {
province: '广东',
city: '深圳'
}
})
}, 1000);
})
// 返回面值列表
app.post('/faceList', (req, res) => {
setTimeout(() => {
res.json(
{
success: true,
obj:['20元', '30元', '50元']
}
)
}, 1000);
})
The last is the getFaceResult of the click event in the front-end page. Since axios returns a promise object, we use the chain writing method of then, first call the getLocation method, get the province and city in its then method, and then call getFaceList inside, and then Get the face value list in the then method of getFaceList
// 点击确定按钮时,获取面值列表
getFaceResult () {
this.getLocation(this.phoneNum).then(res => {
if (res.status === 200 && res.data.success) {
let province = res.data.obj.province;
let city = res.data.obj.city;
this.getFaceList(province, city).then(res => {
if(res.status === 200 && res.data.success) {
this.faceList = res.data.obj
}
})
}
}).catch(err => {
console.log(err)
})
}
Now click the OK button, and you can see the denomination list returned from the background is output on the page. At this time, you see the chain writing of then, and it feels like a callback region. Now we have async/await to transform it.
First, convert getFaceResult into an async function, that is, add async in front of it, because its calling method is the same as that of ordinary functions, so there is no problem. Then just put getLocation and
Put getFaceList after await and wait for execution. The getFaceResult function is modified as follows
// 点击确定按钮时,获取面值列表
async getFaceResult () {
let location = await this.getLocation(this.phoneNum);
if (location.data.success) {
let province = location.data.obj.province;
let city = location.data.obj.city;
let result = await this.getFaceList(province, city);
if (result.data.success) {
this.faceList = result.data.obj;
}
}
}
The way of writing code now is just like writing synchronous code, without the feeling of callback, which is very comfortable.
Now it’s just a little bit to explain, that is, how to deal with the exception, and how to deal with the exception if the request occurs? It uses try/catch to catch exceptions, put await in the try for execution, if there is an exception, use catch for processing.
async getFaceResult () {
try {
let location = await this.getLocation(this.phoneNum);
if (location.data.success) {
let province = location.data.obj.province;
let city = location.data.obj.city;
let result = await this.getFaceList(province, city);
if (result.data.success) {
this.faceList = result.data.obj;
}
}
} catch(err) {
console.log(err);
}
}
Now stop the server, you can see net Erorr output in the console, and the entire program runs normally.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。