1-什么是 Promise ?
在 JavaScript 中,Promise 是一种用于处理异步操作的对象,它可以更加优雅地处理回调函数嵌套和错误处理。
解决的问题:
// 1)回调写起来不好看(难以维护) 恶魔金字塔 嵌套逻辑不优雅 (链式调用 then)
// 2)错误处理无法统一 我们需要处理公共的错误逻辑 (catch)
// 3)尽量简化回调 多个异步并发问题 (Promise.all Promise.finllay)
// promise 依旧是基于回调的,可能还是会有嵌套问题
promise es6已经内部实现了, ie 不兼容 promise,需要 polyfill (比如:es-promise)
2-实现一个简单的promise
// 1) promise 是一个构造函数,默认需要传入一个executor执行器
// 2) executor 会立刻执行,并且传入 resolve 和 reject 两个参数
// 3) promise 有三个状态 fulfilled 成功 reject 拒绝态 pending等待态 (默认是等待态)
// 4)每个promise都有一个then方法 , 可以访问到成功的值和失败的原因
// 5) 可以通过resolve和reject来改变状态,同时调用对应的回调, 一个promise实例状态变化后,不能再重新的发生变化
// 6) 或者当executor 发生异常的时候 也会触发promise的失败
代码实现:
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class Promise {
constructor(executor) {
this.state = PENDING; // new Promise 后 默认状态为pending
this.value = undefined; //成功的原因
this.reason = undefined; //失败的原因
const resolve = (value) => {
//只有状态是pending的时候 才可以修改状态
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
}
};
// 调用executor 会自动传入resolve 与 reject
try {
//或者当executor 发生异常的时候 也会触发promise的失败
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
if (this.state === FULFILLED) {
onFulfilled(this.value);
}
if (this.state === REJECTED) {
onRejected(this.reason);
}
}
}
module.exports = Promise;
//common.js 规范
使用自己的promise
// promise 干什么的,解决的问题是什么?
// 1)回调写起来不好看(难以维护) 恶魔金字塔 嵌套逻辑不优雅 (链式调用 then)
// 2)错误处理无法统一 我们需要处理公共的错误逻辑 (catch)
// 3)尽量简化回调 多个异步并发问题 (Promise.all Promise.finllay)
// promise 依旧是基于回调的,可能还是会有嵌套问题
// 1) promise 是一个构造函数,默认需要传入一个executor执行器
// 2) executor 会立刻执行,并且传入 resolve 和 reject 两个参数
// 3) promise 有三个状态 fulfilled 成功 rejected 拒绝态 pending等待态 (默认是等待态)
// 4)每个promise都有一个then方法 , 可以访问到成功的值和失败的原因
// 5) 可以通过resolve和reject来改变状态,同时调用对应的回调,
// 一个promise实例状态变化后,不能再重新的发生变化
// 6) 或者当executor 发生异常的时候 也会触发promise的失败
const Promise = require("./promise.js");
const promise = new Promise((resolve, reject) => {
console.log("executor");
resolve("ok"); //resolve 与 reject 可以改变promise的状态
reject("error");
});
promise.then(
(data) => {
console.log(data, "success");
},
(err) => {
console.log(err, "reject");
}
);
// console.log(promise);

但是上述代码有个问题:promise 调用 then 方法时可能当前的 promise 并没有成功,而是处于pending 状态。
例如:
const Promise = require("./promise.js");
const promise = new Promise((resolve, reject) => {
console.log("executor");
setTimeout(() => {
// resolve("ok"); //resolve 与 reject 可以改变promise的状态
reject("error");
}, 1000);
});
promise.then(
(data) => {
console.log(data, "success1");
},
(err) => {
console.log(err, "reject1");
}
);
promise.then(
(data) => {
console.log(data, "success2");
},
(err) => {
console.log(err, "reject2");
}
);
// console.log(promise);

他并没有执行回调函数 ,但是这个问题很好解决 只要一个简单的发布订阅模式,如果当前状态是pending状态是,先将所有的回调函数储存起来,待等到相应状态依次调用储存的回调函数。 代码如下:
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class Promise {
constructor(executor) {
this.state = PENDING; // new Promise 后 默认状态为pending
this.value = undefined; //成功的原因
this.reason = undefined; //失败的原因
// 发布订阅模式
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
// promise调用then的时候 可能状态依旧是pending,那么我们需要将回调先存放起来
// 等待过一会调用resolve时触发 onResolvedCallbacks 执行
// 等待调用 reject时触发 onRejectedCallbacks 执行
const resolve = (value) => {
//只有状态是pending的时候 才可以修改状态
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach((cb) => cb());
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason; //先赋值 后执行
this.onRejectedCallbacks.forEach((cb) => cb());
}
};
// 调用executor 会自动传入resolve 与 reject
try {
//或者当executor 发生异常的时候 也会触发promise的失败
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
if (this.state === FULFILLED) {
onFulfilled(this.value);
}
if (this.state === REJECTED) {
onRejected(this.reason);
}
if (this.state === PENDING) {
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value);
});
this.onRejectedCallbacks.push(() => {
onRejected(this.reason);
});
}
}
}
module.exports = Promise;
此时结果:

3-实现promise的链式调用
链式调用可以解决地狱回调问题:
- promise 成功和失败的回调的返回值可以传递到外层的下一个 then
- promise 返回值情况
- 如果返回的是 promise 的情况:会采用 promise 的状态,决定下一步是走成功还是失败
- 如果返回的是普通的值的话:传递到下一次的成功中(不是抛出错误(throw new Error)也不是 promise 就是普通值)
- 如果返回的是抛出错误的情况:一定会走到下一次的失败中
- 错误处理:如果离自己最近的 then 没有错误处理(没有写错误函数)会向下找
- 每次执行完
<font style="color:rgb(199, 37, 78);background-color:rgb(249, 242, 244);">promise.then</font>方法后返回的都是一个新的 promise (promise 一旦成功或者失败都不能去修改状态)
// (1) then链的特点:当then中成功和失败的回调 返回的是一个promise, 内部会解析这个promise, 并将结果传递到外层的下一个then
// (2) 下一次then走成功还是失败, 取决于当前promise的状态
// (3) 如果成功和失败返回的不是一个promise, 那么这个结果直接传递到下一个成功
// (4) 如果成功和失败返回的抛出异常了, 那么这个异常会直接传递到下一个失败
// (5) 让一个promise(then) 变成失败有两种方式, 一种是直接抛出异常, 一种是返回一个失败的promise
readFile(path.resolve(__dirname, "a.txt"), "utf-8")
.then((data) => {
return readFile(data, "utf-8"); // 返回的是一个promise
})
.then(
(data) => {
console.log(data, "success");
},
(err) => {
console.log(err, "error");
return true;
}
)
.then((data) => {
console.log(data, "success2");
throw new Error("error");
})
.then((data)=>{
},(err)=>{
console.log(err, "error2");
})
分别对应返回值的三种情况:

下面来实现一下promise的链式调用:
3-1 实现链式调用里普通值处理
如果返回的是普通的值的话:传递到下一次的成功中(不是错误也不是 promise 就是普通值)resolvePromise函数会做这个处理 后续会写到 先了解一下这个流程。
3-2 实现链式调用里返回的是Promise处理
具体可以参考这个:https://promisesaplus.com/
下面是这两种情况的代码实现:resolvePromise函数统一处理这两种情况,第三种情况是返回的是抛出错误的情况:一定会走到下一次的失败中 (直接有trycatch捕获到error后直接调用reject(e)即可)
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
// 为了让所有人promise 可以互相调用 所有的promise都需要这个规则
function resolvePromise(promise2, x, resolve, reject) {
console.log(promise2,x);
}
class Promise {
constructor(executor) {
this.state = PENDING; // new Promise 后 默认状态为pending
this.value = undefined; //成功的原因
this.reason = undefined; //失败的原因
// 发布订阅模式
// 存放成功回调
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = []; // 存放失败回调
// promise调用then的时候 可能状态依旧是pending,那么我们需要将回调先存放起来
// 等待过一会调用resolve时触发 onResolvedCallbacks 执行
// 等待调用 reject时触发 onRejectedCallbacks 执行
const resolve = (value) => {
//只有状态是pending的时候 才可以修改状态
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach((cb) => cb());
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason; //先赋值 后执行
this.onRejectedCallbacks.forEach((cb) => cb());
}
};
// 调用executor 会自动传入resolve 与 reject
try {
//或者当executor 发生异常的时候 也会触发promise的失败
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
// promise 必须提供 then 方法来存取它当前或最终的值或者原因。
// then 接收两个参数:onFulfilled 和 onRejected
then(onFulfilled, onRejected) {
//new Promise promise会立即执行
let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
// 此时promise2还没有定义 不能将其传进去 所以抱一个setTimeout方法
try {
let x = onFulfilled(this.value); // promise返回的是一个普通值的话 传递到下一个promise中
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
//如果返回的是错误的情况:一定会走到下一次的失败中
reject(e);
}
});
}
if (this.state === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason); // promise返回的是一个普通值的话 传递到下一个promise中
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.state === PENDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
this.onRejectedCal

最低0.47元/天 解锁文章
237

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



