Promise 详解
一.准备
二.promise 的理解
- promise 支持回调函数,可以解决回调地狱的问题。
1.promise的状态
pending
转换成resolved
pending
转换成rejected
promise 只能改变一次,且不能再变了。
2.promise 的属性
- promise 状态
- promsie 属性的值
3.promise 的基本流程
4.promise的API接口
- 构造函数
then
方法
注意,构造函数里的方法,是同步的调用
let p = new Promise((resolve, error) => {
console.log(111);
});
console.log(22);
// 输出
111
222
这说明这部分方法是同步执行的
4.1 catch 用法的接口,只能捕捉失败的方法:
let p = new Promise((resolve, error) => {
error("失败了");
});
p.catch(err => {
console.log(err);
});
//输出
失败了
4.2 promise.all 方法
- promsie.all(),里面接受的包含 n 个 promise的数组,只有所有的都成功了,他才返回成功。`
let p = new Promise((resolve, reject) => {
resolve("ok1");
})
let p1 = Promise.resolve("ok2");
// 除非返回的是个promise对象,而且是错的,否则都是返回对的
let p2 = Promise.resolve("ok3");
let p3 = Promise.all([p1,p2]);
console.log(p3);
返回的结果:
5.promise 状态改变的方法
let p = new Promise((resolve, reject) => {
// 1.调用 resolve 函数
// 2.调用 reject 函数
// 3. throw 一个新的错误
})
6.如果执行 then 函数以后,多个成功或者失败的回调函数都会执行吗?
会的
let p = new Promise((resolve, reject) => {
resolve(1);
})
p.then((value) => {
console.log(value);
})
p.then((value) => {
console.log(value);
})
// 输出结果 为
1
1
7.改变状态和回调的执行顺序
let p = new Promise((resolve, reject) => {
resolve(1); // 如果是同步的,那么就是先改变状态,然后执行then函数
})
p.then((value) => {
console.log(value);
})
如果是异步操作,就是先执行 then 回调,然后改变状态。
let p = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("很好"); // 先执行回调。然后再改变状态
}, 2000);
})
p.then((value) => {
console.log(value);
})
改变状态和执行回调函数谁先谁后:
- 在执行器中直接执行 resolve 函数。
- 让
then
方法等待更长的时间。
什么时候拿到数据?
- 如果先指定回调,然后改变状态,回调函数再执行,最后拿到数据
- 如果先改变状态,然后指定回调函数,回调函数执行,最后拿到数据。
then 方法的返回结果 还是一个 promise
promise 如何串联多个操作任务
使用 promise 有个 .then 方法,使用这个方法,可以返回一个新的 promise 函数,所以可以持续的往后调用。
let p = new Promise((resolve, reject) => {
console.log("11");
resolve();
})
p.then(() => {
console.log("22");
}).then(() => {
console.log("33");
});
// 输出结果
11
22
33
8.异常穿透
当 promise
的 then
调用的时候,所有的异常都会传到最后集中处理
p.then(() => {
console.log("22");
}).then(() => {
console.log("33");
},()=>{
console.log("失败了");
});
// 失败了
所有的异常都会在最后执行;
9.中断 promise 链条
因为空的 prmise 的状态码没有改变,所以他不会返回回调函数。
let p = new Promise((resolve, reject) => {
console.log("11");
resolve();
})
p.then(() => {
console.log("22");
// 有且只有一个方法
return new Promise(() => {})
}).then(() => {
console.log("33");
}, () => {
console.log("失败了");
});
// 输出结果只有 11,22
所以说被终止掉了。
2.使用自带的方法。一个把正常文件转换成 promise 方法的方法
const util = require("util");
const fs = require("fs");
let mineReadField = util.promisify(fs.readFile); // 这样就可以转成 promisify风格的文件
mineReadField("./t1.txt").then((value) => {
console.log(value.toString());
}, () => {
console.log("请求失败");
})
10
三.自定义 promise
function Pro(execut) {
this.State = "pendding";
this.Resulter = null;
this.callbacks = [];
const self = this;
function resolve(data) {
if (self.State !== "pendding") {
return;
}
self.pendding = "resovled";
this.Resulter = data;
self.callbacks.forEach(item => {
item.onResolved(item);
})
}
function reject(data) {
if (self.State !== "pendding") {
return;
}
self.pendding = "rejected";
this.Resulter = data;
self.callbacks.forEach(item => {
item.onRejected(item);
})
}
try {
execut(resolve, reject); // 要立即执行
} catch (e) {
reject(e);
}
}
Pro.prototype.then = function (onResolved, onRejected) {
if (this.State === "resovled") {
onResolved(this.Resulter);
}
if (this.State === "rejected") {
onRejected(this.Resulter);
}
if (this.State === "pendding") { // 异步调用的时候注意
this.callbacks.push({
onResolved,
onRejected,
});
}
}
四. async 和 await
五.JS 异步调用之宏队列和await
六.promise相关问题
参考资料
[1]https://www.bilibili.com/video/BV1MJ41197Eu?share_source=copy_web