文章目录
Promise
三种状态
-
pending -> resolved -> 或pending -> rejected
-
变化不可逆
const p1 = new Promise((resolve, reject) => {
})
console.log("p1", p1)
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
})
})
console.log("p2", p2)
setTimeout(() => console.log("p2-setTimeout", p2))
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject();
})
})
console.log("p3", p3)
setTimeout(() => console.log("p3-setTimeout", p3))
状态的表现
- pending状态不会触发then和catch
- resolve会触发then和catch
- reject会触发catch
then和catch的改变状态
- then正常返回resolved,里面有报错则返回rejected
- catch正常返回resolved,里面有报错则返回rejected
const p1 = Promise.resolve().then(() => {
return 100;
});
console.log("p1", p1);
p1.then(() => {
console.log("p1 then");
});
const p2 = Promise.resolve().then(() => {
throw new Error("then error");
});
console.log("p2", p2);
p2.then(() => {
console.log("p2 then");
}).catch((err) => {
console.log("p2 catch error", err);
});
const p3 = Promise.reject("p3 error").catch(err => {
console.error(err);
});
console.log("p3", p3); // resolved 触发一个then回调
p3.then(() => {
console.log("p3 then");
});
const p4 = Promise.reject("p3 error").catch(err => {
throw new Error("p4 catch error");
});
console.log("p4", p4); // rejected 触发一个catch回调
p4.then(() => {
console.log("p4 then"); // 不会打印
}).catch((err) => {
console.log("p4 catch", err);
});
Promise题目
Promise.resolve().then(() => {
console.log(1);
}).catch(() => {
console.log(2);
}).then(() => {
console.log(3);
})
12
Promise.resolve().then(() => { // 报错返回rejected
console.log(1);
throw new Error("error1");
}).catch(() => { // 没报错返回resolved状态
console.log(2);
}).then(() => {
console.log(3);
})
123
Promise.resolve().then(() => {
console.log(1);
throw new Error("error1");
}).catch(() => {
console.log(2);
}).catch(() => {
console.log(3);
})
12
async-await
异步的发展
- 异步回调 callback 和hell
问题:回调地狱
-
Promise then catch 链式调用,但是也是基于回调函数
-
async-await 是同步语法,彻底消灭回调函数
async-await基本用法
- await后面跟Promise函数
- await后面跟async函数
async-await与Promise的关系
-
async-await是消灭异步回调的最终手段
-
但是和Promise并不互斥,反而相辅相成
-
执行async函数 返回的一定是Promise对象
-
try-catch可捕获异常,取代了.catch
async 执行必定返回Promise对象
async function fn1() {
// return "fn1" // 相当于 return Promise.resolve("fn1")
return Promise.resolve(200);
}
const res1 = fn1();
console.log(res1);
res1.then(data => {
console.log("res1 data", data);
});
await 相当于then()
(async function () {
const p1 = Promise.resolve(300);
const data = await p1;
console.log("data", data);
})();
(async function () {
const p1 = await 400; // 相当于 await Promise.resolve(400)
const data = await p1;
console.log("data", data);
})();
(async function () {
const p1 = await fn1();
const data = await p1;
console.log("data", data);
})();
try-catch
(async function () {
const p4 = Promise.reject("err");
try{
const res = await p4;
console.log(res);
}catch (err) {
console.log("err1", err)
}
})();
(async function () {
const p5 = Promise.reject("err");
const res = await p4; // 此时是rejected状态,不会执行,try-catch可解决
console.log(res)
})();
异步的本质还是回调函数
- js是单线程,异步是基于event loop
- async await 只是一个语法糖
async function async1() {
console.log("async1 start");
await async2();
// await 的后面行代码都会变为异步
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
console.log("script start");
async1();
console.log("script end");
打印
script start
async1 start
async2
script end
async1 end
先执行完同步代码
启动event loop
执行异步代码
增加一个async函数
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
await async3();
console.log("async1 end 2");
}
async function async2() {
console.log("async2");
}
async function async3() {
console.log("async3");
}
console.log("script start");
async1();
console.log("script end");
打印
script start
async1 start
async2
script end
async1 end
async3
async1 end 2
for-of 的应用场景
- for-in是常规的同步遍历
- for-of 常用于异步的遍历
普通异步的遍历代码如下
function muti(num) {
return new Promise(resolve => {
setTimeout(() => {
resolve(num * num);
}, 1000);
});
}
const nums = [1, 2, 3];
nums.forEach(async (i) => {
const res = await muti(i);
console.log(res);
});
1s后全部同时打印出来
如果需要一次一个一秒打印出来时就需要用到for-of
注意await
需要使用async
函数包裹才能执行
function muti(num) {
return new Promise(resolve => {
setTimeout(() => {
resolve(num * num);
}, 1000);
});
}
const nums = [1, 2, 3];
!(async function () {
for (let i of nums) {
const res = await muti(i);
console.log(res);
}
})();