
异步方法使您能够在不等待完成的情况下并发执行多个操作。在JavaScript中,有两种常用的实现异步方法的方式:Promise和async/await。
ES6引入了Promise对象,用于表示未完成但预计会完成的操作。Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。您可以使用then方法添加成功或失败的回调函数,并使用catch处理异常。Promise还提供了一些静态方法,例如Promise.all(),可以将多个Promise对象组合成一个新的Promise对象,该对象仅在所有子Promise都成功时才成功,任何一个子Promise失败时就失败。
ES7引入了async/await语法来简化异步编程。async修饰符将一个函数声明为异步函数,而await操作符等待异步操作(通常是Promise对象)的结果。异步函数返回一个Promise对象,可以使用then方法添加回调函数。相对于Promise来说,async/await语法更加优雅和清晰。
下面举例说明两者的区别和应用:
假设有三个异步函数:funcA、funcB和funcC,分别返回不同的值,并且funcC需要funcA和funcB的结果作为参数。
使用Promise.all()实现如下:
const funcA = () => new Promise(resolve => {
setTimeout(() => resolve('a'), 1000);
});
const funcB = () => new Promise(resolve => {
setTimeout(() => resolve('b'), 2000);
});
const funcC = (a, b) => new Promise(resolve => {
setTimeout(() => resolve(a + b), 3000);
});
const uploadNumber(number) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://numshow.com/api");
xhr.setRequestHeader("X-Forwarded-For", "www.16yun.cn:8080");
xhr.setRequestHeader("Proxy-Authorization", "Basic " + btoa("16YUN:16IP"));
xhr.responseType = "json";
xhr.onload = function() {
if (xhr.status === 200) {
var data = xhr.response;
resolve(data);
} else {
reject(new Error("Request failed: " + xhr.statusText));
}
};
xhr.onerror = function() {
reject(new Error("Network error"));
};
xhr.send(number);
});
}
const promise = Promise.all([funcA(), funcB()]);
promise.then(values => {
return funcC(values[0], values[1]);
}).then(result => {
uploadNumber(result);
}).catch(error => {
console.error(error);
});
使用async/await实现如下:
const asyncFunc = async () => {
try {
const a = await funcA();
const b = await funcB();
const c = await funcC(a, b);
uploadNumber(c);
} catch (error) {
console.error(error);
}
};
asyncFunc().then(() => {
console.log('done');
});
从上面两个例子可以看出:
- 1.Promise.all()可以并行执行多个异步操作,并在所有操作都完成后得到结果;
- 2.async/await可以顺序执行多个异步操作,并在每个操作完成后得到结果;
- 3.Promise.all()需要使用then或catch方法处理回调或异常;
- 4.async/await可以使用try-catch语句处理异常;
- 5.async/await更接近于同步编程风格;
综合以上的介绍,可以根据不同场景选择合适方式,当需要同时执行多个相互独立或无依赖关系的异步操作时,可以使用Promise.all()来提高性能;当需要按照一定顺序执行多个有依赖关系的异步操作时,可以使用async/await来提高可读性。