Async/Await 也就是你们知道的异步函数,它是一个用来控制 JavaScript 异步流程的一个记号。而在不少现代浏览器上也曾实现过这样的设想。它的灵感来源于C# 和 F#,如今 Async/Await 在ES2017已经平稳着陆。javascript
一般咱们认为 async function
是一个能返回 Promise
的 function
。你也能够在 async function
使用 await
关键字。 await
关键字能够放在一个须要返回Promise的表达式前,所获得的值被从Promise里面剥离开,以便能用更直观的同步体验。咱们来看一下实际的代码更直观。java
// 这是一个简单的返回 Promise 函数
// 功能是在两秒之后 resolve("MESSAGE") .
function getMessage() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("MESSAGE"), 2000);
});
}
复制代码
async function start() {
const message = await getMessage();
return `The message is: ${message}`;
}
复制代码
start().then(msg => console.log(msg));
// "The message is: MESSAGE"
复制代码
Async/Await 提供了一个看起来相对同步的方法来执行异步代码。同时也提供了一种简洁而直观的方法来处理异步的错误,由于它实现了try…catch
标记,这是JavaScript里面最多见的一种同步模式。node
在咱们开始冒险以前,咱们应该清楚,Async/Await 是创建在 JavaScript Promises 上的,并且关于它的知识是很重要的。json
要建立一个 async
函数,通常就要把 async
关键字放在声明函数以前,就像这样:api
async function fetchWrapper() {
return fetch('/api/url/');
}
const fetchWrapper = async () => fetch('/api/url/');
复制代码
const obj = {
async fetchWrapper() {
// ...
}
}
复制代码
async function updateBlogPost(postId, modifiedPost) {
const oldPost = await getPost(postId);
const updatedPost = { ...oldPost, ...modifiedPost };
const savedPost = await savePost(updatedPost);
return savedPost;
}
复制代码
在这里的 await
是用在其余返回 promise 的函数前。在第一行,oldPost被赋值为getPost执行resolve后返回的value。在下一行,咱们使用了解构赋值来演示怎样把 oldPost 和 modifiedPost 合并。最终咱们把 post 储存下来,返回了 savedPost 的结果。promise
🖐️“到底怎么处理错误?”浏览器
这是一个好问题!当你使用 async/await 的时候,你也能够使用 try...catch
。在下面展现了,咱们异步的 fetch 了一些东西,返回了某种错误,咱们能够在catch里面拿到错误。bash
async function tryToFetch() {
try {
const response = await fetch('/api/data', options);
return response.json();
} catch(err) {
console.log(`An error occured: ${err}`);
// 比起返回一个错误
// 咱们能够返回一个空的data
return { data: [] };
}
}
复制代码
tryToFetch().then(data => console.log(data));
复制代码
🖐️ ️“我仍是不知道为何 async/await 比 callbacks/promises 好.”并发
很高兴你问了这个问题,这里有一个例子能够说明不一样。咱们这里只是想要异步的 fetch 一些数据,而后获得数据后,简单的返回一些通过处理的data,若是有错误,咱们简单的只是想要返回一个对象。app
// 咱们这里有 fetchSomeDataCB, 和 processSomeDataCB
// NOTE: CB 表明 callback
function doWork(callback) {
fetchSomeDataCB((err, fetchedData) => {
if(err) {
callback(null, [])
}
processSomeDataCB(fetchedData, (err2, processedData) => {
if(err2) {
callback(null, []);
}
// return the processedData outside of doWork
callback(null, processedData);
});
});
}
doWork((err, processedData) => console.log(processedData));
复制代码
// 咱们这里有 fetchSomeDataP, 和 processSomeDataP
// NOTE: P 意味着这个函数返回一个 Promise
function doWorkP() {
return fetchSomeDataP()
.then(fetchedData => processSomeDataP(fetchedData))
.catch(err => []);
}
doWorkP().then(processedData => console.log(processedData));
复制代码
async function doWork() {
try {
const fetchedData = await fetchSomeDataP();
return processSomeDataP(fetchedData);
} catch(err) {
return [];
}
}
doWork().then(processedData => console.log(processedData));
复制代码
Callback vs Promise vs Async/Await
🖐️“他的并发性如何”
当咱们须要有顺序的作一些事情,咱们一般用await一个一个声明全部的步骤。在这以前为了理解并发,咱们必须使用Promise.all
。若是咱们如今有三个异步动做须要平行执行,在加上await以前,咱们须要让全部的Promise先开始。
// 这不是解决方法,他们会逐个执行
async function sequential() {
const output1 = await task1();
const output2 = await task2();
const output3 = await task3();
return combineEverything(output1, output2, output3);
}
复制代码
由于上述代码只是依次的执行了三个任务,而没有并发的执行,后一个会依赖前一个执行完成。因此咱们要改形成Promise.all
的方式。
// 这就能够并发的执行
async function parallel() {
const promises = [
task1(),
task2(),
task3(),
];
const [output1, output2, output 3] = await Promise.all(promises);
);
return combineEverything(output1, output2, output3);
}
复制代码
在这个例子上,咱们首先执行了3个异步的任务,以后把Promise都储存进了一个array。咱们使用 Promise.all
来完成来所有并发结果的收集。
await
一些代码, 你须要声明这个函数是一个 async function
。await
时候,它值暂停了所涉及的 async function
。 换句话说,下面的代码会在其余东西log以前log 'wanna race?'
。const timeoutP = async (s) => new Promise((resolve, reject) => {
setTimeout(() => resolve(s*1000), s*1000)
});
复制代码
[1, 2, 3].forEach(async function(time) {
const ms = await timeoutP(time);
console.log(`This took ${ms} milliseconds`);
});
复制代码
console.log('wanna race?');
复制代码
当你的第一个await 的 promise在主线程上返回执行告终果,在forEach外面的log不会被阻塞。
看一看这张浏览器支持表。
node 7.6.0
以及以上版本支持 Async/Await !
原文:Asynchronous Adventures in JavaScript: Async/Await
翻译:Dominic Ming