同步和异步
同步编程
必须等前一个任务执行完成后,才能进行下一个任务。
异步编程
在执行任务a的时候,也可以执行任务b。
实现异步编程的方法:
1. 回调函数
//假定有两个函数f1和f2,后者等待前者的执行结果。
//假如f1是做汉堡,f2是吃汉堡,f1很耗时,但是f2需要等待f1执行完才能执行
//而主程序不想等待这个耗时的函数
f1();
f2();
//可以考虑改写f1,把f2写成f1的回调函数。
function f1(callback){
setTimeout(function () {
// f1的任务代码
callback();
}, 1000);
}
//执行代码就变成下面这样:
//于是主程序可以不管f1和f2,先继续执行主程序
f1(f2);
2. 事件监听
任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
3. Promise
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
resolve
函数在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject
函数在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise
实例生成以后,可以用then
方法分别指定resolved
状态和rejected
状态的回调函数。
promise.then(function(value) {
// success
}, function(error) {
// failure
});
4. async
当执行到 await
表达式时,以下过程发生:
- JavaScript 引擎看到
await
关键字,它会暂停async
函数的执行。 - 引擎将出让控制权,允许async函数外的其他代码运行。
- 一旦
await
后面的 Promise 解决或拒绝,async
函数将恢复执行。
async function() {
... (A) 同步代码执行
await promise; // 异步等待 Promise 解决
... (B) 当 Promise 解决后执行的代码
}
... (C) 在 async 函数外面的代码
执行顺序如下:
(A)
执行。await
暂停async function
的执行。(C)
执行(即使它是在async function
暂停之后的代码)。- Promise 解决。
(B)
执行。
如何处理多个异步请求
并行执行多个异步操作,并且只有在all异步操作都成功完成时才继续执行时,可以使用 Promise.all
:
let promise1 = fetch(url1);
let promise2 = fetch(url2);
let promise3 = fetch(url3);
Promise.all([promise1, promise2, promise3])
.then((results) => {
// 所有请求都成功响应。
// results 数组包含每个 Promise 的结果
const [response1, response2, response3] = results;
// 处理每个响应
})
.catch((error) => {
// 如果任何一个请求失败,这里会执行
console.error("Failed to fetch:", error);
});
多个请求中只要有一个成功就继续执行,并且忽略所有的失败,可以使用 Promise.any
:
Promise.any([promise1, promise2, promise3])
.then((firstSuccessfulResult) => {
// 第一个成功解决的 Promise 的结果
console.log('第一个成功的请求的结果:', firstSuccessfulResult);
})
.catch((error) => {
// 如果所有 Promise 都失败,这里会执行
console.error("所有请求都失败:", error);
});