JS学习-async/await
async/await
- 它保证函数的返回值为 promise。
- 用更少的.then()块来封装代码,同时它看起来很像同步代码
注意:可能会因为大量await的promises相继发生而变慢。
async关键字
使用 async 关键字,把它放在函数声明之前,使其成为 async function。
let hello = async function() {
return "Hello"
};
//let hello = async () => { return "Hello" };
hello(); //Promise { <state>: "fulfilled", <value>: "Hello" }
await关键字
await 只在异步函数里面才起作用。
promise & async/await
//promise
fetch('coffee.jpg').then(response => response.blob())
.then(myBlob => {
let image = document.createElement('img');
image.src = URL.createObjectURL(myBlob);
document.body.appendChild(image);
}).catch(e => {
console.log('an error with fetch img: ' + e.message);
});
//async/await
async function fetchImg(){
try{
let myFetch = await fetch('coffee.jpg');
let myBlob = await myFetch.blob();
let image = document.createElement('img');
image.src = URL.createObjectURL(myBlob);
document.body.appendChild(image);
}catch(e){
console.log('an error with fetch img: ' + e);
}
}
//promise + async/await
(async function fetchImg(){
let myFetch = await fetch('coffee.jpg');
return await myFetch.blob();
})().then(blob=>{
let image = document.createElement('img');
image.src = URL.createObjectURL(myBlob);
document.body.appendChild(image);
}).catch(e => {
console.log('an error with fetch img: ' + e.message);
});
async/await 的缺点
await
关键字会阻塞其后的代码,直到promise完成,就像执行同步操作一样。
这意味着您的代码可能会因为大量await
的promises
相继发生而变慢。每个await
都会等待前一个完成,而你实际想要的是所有的这些promises
同时开始处理(就像我们没有使用async/await时那样)。
有一种模式可以缓解这个问题——通过将 Promise
对象存储在变量中来同时开始它们,然后等待它们全部执行完毕。
function timeoutPromise(time) {
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve("done");
}, time);
});
};
let startTime = Date.now();
timeTest().then(() => {
let timeTaken = Date.now() - startTime;
alert("Time taken in milliseconds: " + timeTaken);
})
//slow:大约是9s
async function timeTest() {
await timeoutPromise(3000);
await timeoutPromise(3000);
await timeoutPromise(3000);
}
//fast:大约是3s
async function timeTest() {
const timeoutPromise1 = timeoutPromise(3000),timeoutPromise2 = timeoutPromise(3000),timeoutPromise3 = timeoutPromise(3000);
await timeoutPromise1;
await timeoutPromise2;
await timeoutPromise3;
}
//or:大约是3s
await Promise.all([timeoutPromise(3000),timeoutPromise(3000),timeoutPromise(3000)]);
旧式异步回调的缺点
- 嵌套回调可能很麻烦且难以阅读(即“回调地狱”)
- 每层嵌套都需要故障回调,而使用promises,您只需使用一个.catch()代码块来处理整个链的错误。
- 异步回调不是很优雅。
- Promise回调总是按照它们放在事件队列中的严格顺序调用;异步回调不是。
- 当传入到一个第三方库时,异步回调对函数如何执行失去完全控制。