async/await
的目的是简化使用 promises 的写法。
让我们来看看下面的例子:
// 一个标准的 JavaScript 函数
function getNumber1() {
return Promise.resolve('374');
}
// 这个 function 做了和 getNumber1 同样的事
async function getNumber2() {
return 374;
}
同样,抛出异常的函数等于返回已失败的 promises:
function f1() {
return Promise.reject('Some error');
}
async function f2() {
throw 'Some error';
}
关键字 await
只能使用在 async
的函数中,并允许你同步等待一个 Promise。如果我们在 async
函数之外使用 promise,我们仍然要用 then
回调函数:
async function loadData() {
// `rp` 是一个请求异步函数
var promise1 = rp('https://api.example.com/endpoint1');
var promise2 = rp('https://api.example.com/endpoint2');
// 现在,两个请求都被触发,
// 我们就等待它们完成。
var response1 = await promise1;
var response2 = await promise2;
return response1 + ' ' + response2;
}
// 但,如果我们没有在 `async function` 里
// 我们就必须使用 `then`。
loadData().then(() => console.log('Done'));
区别:
- 干净的代码: 使用 async/await 能够让你少写代码。每一次你使用 async/await 你都能跳过一些不必要的步骤:写一个 .then,创建一个匿名函数来处理响应,在回调中命名响应,比如:
// `rp` 是一个请求异步函数
rp(‘https://api.example.com/endpoint1').then(function(data) {
// …
});
对比:
// `rp` 是一个请求异步函数
var response = await rp(‘https://api.example.com/endpoint1');
- 错误处理: Async/await 使得我们可以使用相同的代码结构处理同步或者异步的错误 —— 著名的 try/catch 语句。
async function loadData() {
try {
var data = JSON.parse(await getJSON());
console.log(data);
} catch(e) {
console.log(e);
}
}
- 条件语句: 使用
async/await
来写条件语句要简单得多:
function loadData() {
return getJSON()
.then(function(response) {
if (response.needsAnotherRequest) {
return makeAnotherRequest(response)
.then(function(anotherResponse) {
console.log(anotherResponse)
return anotherResponse
})
} else {
console.log(response)
return response
}
})
}
对比:
async function loadData() {
var response = await getJSON();
if (response.needsAnotherRequest) {
var anotherResponse = await makeAnotherRequest(response);
console.log(anotherResponse)
return anotherResponse
} else {
console.log(response);
return response;
}
}
- 栈帧: 和
async/await
不同的是,根据promise链返回的错误堆栈信息,并不能发现哪出错了。来看看下面的代码:
function loadData() {
return callAPromise()
.then(callback1)
.then(callback2)
.then(callback3)
.then(() => {
throw new Error("boom");
})
}
loadData()
.catch(function(e) {
console.log(err);
// Error: boom at callAPromise.then.then.then.then (index.js:8:13)
});
对比:
async function loadData() {
await callAPromise1()
await callAPromise2()
await callAPromise3()
await callAPromise4()
await callAPromise5()
throw new Error("boom");
}
loadData()
.catch(function(e) {
console.log(err);
// 输出
// Error: boom at loadData (index.js:7:9)
});
- 调试: 如果你使用了 promises,你就会知道调试它们将会是一场噩梦。比如,你在 .then 里面打了一个断点,并且使用类似 “stop-over” 这样的 debug 快捷方式,调试器不会移动到下一个 .then,因为它只会对同步代码生效。而通过
async/await
你就可以逐步的调试 await 调用了,它就像是一个同步函数一样。
参考: https://github.com/xitu/gold-miner/blob/master/TODO/how-javascript-works-event-loop-and-the-rise-of-async-programming-5-ways-to-better-coding-with.md