JavaScript中异步从来都不简单,很长一段时间内, 我们都是使用的回调来实现。后来,我们可以使用promise,现在,我们可以使用async和await(以下简称异步函数)来实现异步。
虽然异步函数的出现使得编写异步函数更加容易了,但是同样也存在陷阱,并且对于初学者并不是那么的友好。
在这篇文章的两个部分中,我将和你们一起分享一切你需要知道的关于异步函数的知识。
Asynchronous functions
异步函数包含async关键字,你可以像普通的函数声明一样使用它:
async function functionName (arguments) {
//Do something asynchronous
}
你也可以使用箭头函数
const functionName = async (arguments) => {
//Do something asynchronous
}
Asynchronous functions always return promise
返回什么值并不重要,使用异步函数返回的值总是一个promise
const getOne = async _ => {
return 1;
}
const promise = getOne();
console.log(promise) // Promise
await关键词
当你调用一个promise时,你使用then来进行下一步,就像这样:
const getOne = async _ => {
return 1;
}
getOne()
.then(value => {
console.log(value); // 1
})
await关键词让你定义reslove函数,一旦promise成功了,它就会返回传递到then函数的参数。
const test = async _ => {
const one = await getOne();
console.log(one);
}
test();
Return await
在返回一个promise之前,等待是没有必要的,你可以直接返回promise.
如果你返回一个await, 你先实现了原来的promise,然后,你又创建一个新的promise,return await虽然不影响什么,但是没有必要多此一举。
//Don't need to do this
const test = async _ => {
return await getOne();
}
test()
.then(value => {
console.log(value); // 1
})
//Do this instead
const test = aysnc _ => {
return getOne();
}
test()
.then(value => {
console.log(value); //1
})
注意,如果你不需要await,你不许要使用异步函数。上面的列子可重写。
//Do this instead
const test = _ => {
return getOne();
}
test()
.then(value => {
console.log(value); // 1
});
Handling errors
如果一个promise导致了错误,你可以使用catch来捕捉他
const getOne = aysnc (success = true) => {
if (success) return 1;
throw new Error('failure');
}
getOne(false)
.then(error => console.log(error)); // failure
如果你想在异步函数中处理错误,你需要使用一个try/catch来捕捉它。
const test = async _ => {
try {
const one = await getOne(false);
}catch (e) {
console.log(e); //failure
}
}
test();
如果你有多个await关键词,这样写错误处理会变的很丑
const test = async _ => {
try {
const one = await getOne(false);
}catch (e) {
console.log(e); //failure
}
try {
const two = await getTwo(false);
}catch (e) {
console.log(e); //failure
}
try {
const three = await getThree(false);
}catch (e) {
console.log(e); //failure
}
}
test();
但是还有一个更好的办法。
我们知道异步函数总是返回一个promise,当我们调用一个promise,我们在catch中处理错误。这意味这我们可以通过添加catch来处理错误。
const test = async _ => {
const one = await getOne(false);
const two = await getTwo(false);
const three = await getThree(false);
}
test()
.catch(error => console.log(error));
注意: Promise方法只会让你捕捉一个错误。
Multiple awaits
await会阻塞js执行下一行代码,知道promise的resolve被执行完成。这可能会降低执行的效率。
我们需要创建一个延迟来在实际中演示,通过sleep来创建延迟。
const sleep = ms => {
return new Promise(resolve => setTimeout(resolve, ms));
}
//Using Sleep
console.log('Now');
sleep(1000)
.then(value => console.log('after one second')); // print 'now' immediately, 'after one second' printed in console after 1 second
现在我们来看需要等三个promise的情况,每一个promise都有一个一秒的延迟。
const getOne = _ => {
return sleep(1000).then(val => 1)
}
const getTwo = _ => {
return sleep(1000).then(val => 1)
}
const getThree = _ => {
return sleep(1000).then(val => 1)
}
如果你await这些promises在一行中,你将不得不等待3秒在那些promise全部结束之前。这不是很好因为我们强迫JavaScript等待额外的2秒在做我们需要的之前。
const test = async _ => {
const one = await getOne();
console.log(one);
const two = await getTwo();
console.log(two);
const three = await getThree();
console.log(three);
console.log('Done');
}
test(); //Console shows ‘Now’ immediately. One second later, it shows 1. Another second later, it shows 2. Another second later, it shows 3 and ‘Done’ at the same time.
如果getOne, getTwo, getThree可以同时(simultraneously)执行,你可以节省两秒。你可以使用promise.all同时执行三个promise.
const test = async _ => {
const promise = [getOne(), getTwo(), getThree()];
console.log('Now');
const [one, two, three] = await Promise.all(promise);
console.log(one);
console.log(two);
console.log(three);
console.log('Done');
};
Console shows ‘Now’ immediately. After one second, console shows 1, 2, 3, and ‘Done’
欢迎补充。


被折叠的 条评论
为什么被折叠?



