async关键字
- 普通函数调用,返回"Hello"
function hello() { return "Hello" };
hello(); //"Hello"
- 声明async调用,返回一个promise
async function hello() { return "Hello" };
hello(); //Promise {<resolved>: "Hello"}
以下是等价的写法:
//创建一个异步函数表达式
let hello = async function() { return "Hello" };
hello();
//使用箭头函数
let hello = async () => { return "Hello" };
hello();
- 因为返回了一个promise,我们可以使用.then()块
hello().then((value) => console.log(value)); //Hello
//简写
hello().then(console.log); //Hello
await关键字
可以在调用任何返回Promise的函数时使用await,包括Web API函数。
await关键字使JavaScript运行时暂停此行上的代码,允许其他代码在此期间执行,直到异步函数调用返回其结果。一旦完成,您的代码将继续从下一行开始执行。
async function hello() {
return greeting = await Promise.resolve("Hello");
};
hello().then(alert); //Hello
- Can’t use await in regular functions
function f() {
let promise = Promise.resolve(1);
let result = await promise; //Uncaught SyntaxError: await is only valid in async function
}
- await won’t work in the top-level code
<!DOCTYPE html>
<html lang="en">
<body>
</body>
<script>
'use strict';
// syntax error in top-level code
let response = await fetch('https://cnodejs.org/api/v1/topics');
let user = await response.json();
console.log(user);
</script>
</html>
we can wrap it into an anonymous async function
<script>
'use strict';
// syntax error in top-level code
(async () => {
let response = await fetch('https://cnodejs.org/api/v1/topics');
let user = await response.json();
alert(user);
})();
</script>
- await accepts “thenables”
class Thenable {
constructor(num) {
this.num = num;
}
then(resolve, reject) {
// resolve with this.num*2 after 1000ms
setTimeout(() => resolve(this.num * 2), 1000); // (*)
}
};
async function f() {
// waits for 1 second, then result becomes 2
let result = await new Thenable(1);
console.log(result);
}
f();
- 类方法
我们可以在类/对象方法前面添加async,以使它们返回promises,并await它们内部的promises。
class Person {
constructor(name) {
this.name = name;
}
async greeting() {
return await Promise.resolve(`Hi! I'm ${this.name}.`);
};
}
let jim = new Person('Jim');
jim.greeting().then(console.log); //Hi! I'm Jim.
使用async/await重写promise代码
- promise实现
fetch('https://cnodejs.org/api/v1/topics')
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(e => {
console.log('There has been a problem with your fetch operation: ' + e.message);
});
- 使用async/await实现
async function myFetch() {
let response = await fetch('https://cnodejs.org/api/v1/topics');
let data = await response.json();
console.log(data);
}
myFetch()
.catch(e => {
console.log('There has been a problem with your fetch operation: ' + e.message);
});
- 重构代码
async function myFetch() {
let response = await fetch('https://cnodejs.org/api/v1/topics');
return await response.json();
}
myFetch().then((data) => {
console.log(data);
})
添加错误处理
async function myFetch() {
try {
let response = await fetch('https://cnodejs.org/api/v1/topics');
let data = await response.json();
console.log(data);
} catch(e) {
console.log(e);
}
}
myFetch();
async function myFetch() {
let response = await fetch('https://cnodejs.org/api/v1/topics');
return await response.json();
}
myFetch().then((data) => {
console.log(data);
})
.catch((e) =>
console.log(e)
);
等待Promise.all()
async/await建立在promises之上,因此它与promises提供的所有功能兼容。
async function myFetch(url) {
const response = await fetch(url);
return await response.json();
}
async function init() {
let topicList = myFetch('https://cnodejs.org/api/v1/topics');
let topicItem = myFetch('https://cnodejs.org/api/v1/topic/5e4fa8531225c9423dcda9d8');
let userInfo = myFetch('https://cnodejs.org/api/v1/user/lellansin');
let values = await Promise.all([topicList, topicItem, userInfo]);
console.log(values);
}
async/await的缺陷
async/await让你的代码看起来是同步的,在某种程度上,也使得它的行为更加地同步。 await关键字会阻塞其后的代码,直到promise完成.
代码可能会因为大量await的promises相继发生而变慢。每个await都会等待前一个完成,而你实际想要的是所有的这些promises同时开始处理(就像我们没有使用async/await时那样)。
有一种模式可以缓解这个问题 ––通过将Promise对象存储在变量中来同时开始它们,然后等待它们全部执行完毕。
function timeoutPromise(interval) {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve("done");
}, interval);
});
};
async function timeTestSlow() {
await timeoutPromise(3000);
await timeoutPromise(3000);
await timeoutPromise(3000);
}
let startTime = Date.now();
timeTestSlow().then(() => {
let finishTime = Date.now();
let timeTaken = finishTime - startTime;
console.log("Time taken in milliseconds: " + timeTaken); //Time taken in milliseconds: 9013
})
另一种写法
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
};
async function timeTestSlow() {
await timeout(3000);
await timeout(3000);
await timeout(3000);
}
function doit(){
console.time("doit");
timeTestSlow().then(() => {
console.timeEnd("doit");
})
}
doit(); //doit: 9008.90380859375ms
保存在变量中
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
};
async function timeTestFast() {
const timeout1 = timeout(3000);
const timeout2 = timeout(3000);
const timeout3 = timeout(3000);
await timeout1;
await timeout2;
await timeout3;
}
function doit(){
console.time("doit");
timeTestFast().then(() => {
console.timeEnd("doit");
})
}
doit(); //doit: 3002.612060546875ms
More
Making asynchronous programming easier with async and await
developer.mozilla.org/en-US/docs/…
async和await:让异步编程更简单 developer.mozilla.org/zh-CN/docs/…
理解 JavaScript 的 async/await
segmentfault.com/a/119000000…
async 函数的含义和用法
www.ruanyifeng.com/blog/2015/0…
Async/Await:比Promise更好的6个理由
caibaojian.com/asyncawait.…