目录
- 一、介绍
- 二、初始结构
- promise三个状态及结果
- 三、then
- 1、then参数问题
- 2、throw Error问题
- 3、Promise不加异步执行顺序
- 4、Promise加异步执行顺序
- 5、返回Promise对象
- 四、Promise链式操作
- 完整代码
一、介绍
JavaScript Promise 是一种异步编程的解决方案,可以更好地管理和组织异步代码。 Promise 提供了一种更简洁和直观的方法来处理异步操作,而不必依赖于回调函数。
二、初始结构
Promise 是一个对象,表示一个异步操作的最终完成(或失败)及其结果值。Promise 可以有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。当 Promise 对象的状态从 pending 转变为 fulfilled 或 rejected 时,表示异步操作已经完成。以下是一个使用 Promise 的简单示例:
正常我们写代码是这样的。
new Promise((resolve,reject) => {
resolve("learn promise success!");
reject("learn promise error!");
}).then( res => {
console.log(res);
})
根据promise用法和看它源码分析。首先promise会有resolve、reject、then、catch主要方法。这里就只写基础版本,所以得到下面,我们需要去接收外面传进来参数。
/**
* Promise 构造函数
* @param {Function} executor - 执行器函数
*/
class MyPromise {
constructor(executor){
// 将 resolve 函数绑定到 Promise 实例上
this.resolve = (result) => {
// learn promise success!
console.log(result,"result")
}
// 将 reject 函数绑定到 Promise 实例上
this.reject = (error) => {
// learn promise error!
console.log(error,"error")
}
// 执行器函数接受 resolve 和 reject 函数作为参数
executor(this.resolve, this.reject);
}
then(){
}
catch(){
}
}
上面结果是无法打印的。因为MyPromise里面的then没有去给他返回。
promise三个状态及结果
因为promise有三个状态所以我们,分为不同状态,并把状态和结果保存下来。
class SelfPromise {
static PADDIBNG = "等待";
static FULILLED = "成功";
static REJECT = "拒绝";
constructor(executor) {
// 存储 Promise 状态
this.PromiseState = SelfPromise.PADDIBNG;
// 存储 Promise 结果
this.PromiseResult = null;
this.resolve = (result) => {
if(this.PromiseState === SelfPromise.PADDIBNG){
// 更新状态
this.PromiseState = SelfPromise.FULILLED;
// 存储结果
this.PromiseResult = result;
}
};
// 将 reject 函数绑定到 Promise 实例上
this.reject = (error) => {
if(this.PromiseState === SelfPromise.PADDIBNG){
// 更新状态
this.PromiseState = SelfPromise.REJECT;
// 存储结果
this.PromiseResult = error;
}
};
// 执行器函数接受 resolve 和 reject 函数作为参数
executor(this.resolve, this.reject);
}
then(onFulfilled, onRejected) {
}
catch() {}
}
三、then
接下来,我们改写then啦。需要判断对任务处理状态,返回不同的数据
class SelfPromise {
+
+
+
then(onFulfilled, onRejected) {
if(this.PromiseState === SelfPromise.FULILLED){
onFulfilled(this.PromiseResult)
}
if(this.PromiseState === SelfPromise.REJECT){
onRejected(this.PromiseResult)
}
}
catch() {}
}
1、then参数问题
有一点需要注意的是。Promise。then是有两个参数的。所以通过不同状态返回对应结果。
new SelfPromise((resolve,reject) => {
resolve("learn promise success11!");
reject("learn promise error11!");
}).then(
res => console.log(res),
err => console.log(err)
)
如果我们不传两个正常函数可不可以呢,测试了Promise,它并不会抱错。
new Promise((resolve,reject) => {
resolve("learn promise success11!");
reject("learn promise error11!");
}).then(
undefined,
err => console.log(err)
)
但是我们的会,所以需要处理一下,如果不是传的函数,我们需要给它一个默认函数。
class SelfPromise {
+
+
+
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
onRejected = typeof onRejected === 'function' ? onRejected : () => {};
if(this.PromiseState === SelfPromise.FULILLED){
onFulfilled(this.PromiseResult)
}
if(this.PromiseState === SelfPromise.REJECT){
onRejected(this.PromiseResult)
}
}
catch() {}
}
2、throw Error问题
有时候,我们会像下面这样去做,去看了一下Promise,他没有抱错,只是会输出错误信息
new Promise((resolve,reject) => {
throw new Error("不能随便使用啦!")
}).then(
res => console.log(res),
err => console.log(err)
)
但是当前我们代码会抱错,直接扔出错误,导致无法使用,所以我们需要对执行器处理一下。
class SelfPromise {
constructor(){
+
+
try {
// 执行器函数接受 resolve 和 reject 函数作为参数
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error)
}
}
+
+
}
3、Promise不加异步执行顺序
这个时候我们的程序是没有加任何异步的代码,例如常用的setTimeOut都没有用,可以说现在代码还是同步的,我们了解原生Promise的运行顺序规则,接下来为原生代码添加步骤信息。
console.log("第一步")
new Promise((resolve,reject) => {
console.log("第二步")
resolve("执行");
}).then(
res => console.log(res),
err => console.log(err)
)
console.log("第三步")
// 执行顺序结果
第一步
第二步
第三步
执行
再来看看手写的。
console.log("第一步")
new SelfPromise((resolve,reject) => {
console.log("第二步")
resolve("执行");
}).then(
res => console.log(res),
err => console.log(err)
)
console.log("第三步")
// 执行顺序结果
第一步
第二步
执行
第三步
发现顺序不同,这是哪里问题,其实就是因为没有设置异步代码原因,我们给then添加setTimeOut
class SelfPromise {
+
+
+
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
onRejected = typeof onRejected === 'function' ? onRejected : () => {};
if(this.PromiseState === SelfPromise.FULILLED){
onFulfilled(this.PromiseResult)
}
if(this.PromiseState === SelfPromise.REJECT){
onRejected(this.PromiseResult)
}
}
catch() {}
}
再执行,顺序就对了。
4、Promise加异步执行顺序
接下来我们再给原生Promise添加异步
console.log("第一步")
new Promise((resolve,reject) => {
console.log("第二步")
setTimeout(() => {
resolve("执行");
console.log("第四步")
});
}).then(
res => console.log(res),
err => console.log(err)
)
console.log("第三步")
// 执行顺序结果
第一步
第二步
第三步
第四步
执行
接下来给手写代码添加异步
console.log("第一步")
new SelfPromise((resolve,reject) => {
console.log("第二步")
setTimeout(() => {
resolve("执行");
console.log("第四步")
});
}).then(
res => console.log(res),
err => console.log(err)
)
console.log("第三步")
// 执行顺序结果
第一步
第二步
第三步
第四步
通过调试发现,是因为.then没有执行onFulfilled,所以无法输出,刚刚的条件没有满足那两项。还缺少“等待”的状态
class SelfPromise {
+
+
+
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
onRejected = typeof onRejected === 'function' ? onRejected : () => {};
if(this.PromiseState === SelfPromise.PADDIBNG){
}
if(this.PromiseState === SelfPromise.FULILLED){
onFulfilled(this.PromiseResult)
}
if(this.PromiseState === SelfPromise.REJECT){
onRejected(this.PromiseResult)
}
}
catch() {}
}
那等待的期间我们应该做些什么呢,因为这个时候任务还在执行中,等他异步任务处理,等异步处理完之后,执行resolve之后再来执行then,为了保留then里面的函数,我们创建callbacks数组来保存函数。等执行resolve的之后再去执行数组里面的then的回调。
class SelfPromise {
static PADDIBNG = "等待";
static FULILLED = "成功";
static REJECT = "拒绝";
constructor(executor) {
// 存储 Promise 状
this.PromiseState = SelfPromise.PADDIBNG;
// 存储 Promise 结果
this.PromiseResult = null;
+ // 存储 Promise 回调函数
+ this.callbacks = [];
this.resolve = (result) => {
if(this.PromiseState === SelfPromise.PADDIBNG){
// 更新状态
this.PromiseState = SelfPromise.FULILLED;
// 存储结果
this.PromiseResult = result;
+ // 执行回调函数
+ this.callbacks.forEach((callback) => callback.onFulfilled(result));
}
};
// 将 reject 函数绑定到 Promise 实例上
this.reject = (error) => {
if(this.PromiseState === SelfPromise.PADDIBNG){
// 更新状态
this.PromiseState = SelfPromise.REJECT;
// 存储结果
this.PromiseResult = error;
// 执行回调函数
this.callbacks.forEach((callback) => callback.onRejected(result));
}
};
try {
// 执行器函数接受 resolve 和 reject 函数作为参数
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error)
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
onRejected = typeof onRejected === 'function' ? onRejected : () => {};
+ if(this.PromiseState === SelfPromise.PADDIBNG){
+ this.callbacks.push({
+ onFulfilled,
+ onRejected,
+})
+}
if(this.PromiseState === SelfPromise.FULILLED){
setTimeout(()=>{
onFulfilled(this.PromiseResult)
})
}
if(this.PromiseState === SelfPromise.REJECT){
setTimeout(()=>{
onRejected(this.PromiseResult)
})
}
}
catch() {}
}
但是我们发现还是不行,执行顺序还是没有变化。同理,我们给resolve、reject添加setTimeOut。
class SelfPromise {
constructor(){
+
+
this.resolve = (result) => {
setTimeout(() => {
if(this.PromiseState === SelfPromise.PADDIBNG){
// 更新状态
this.PromiseState = SelfPromise.FULILLED;
// 存储结果
this.PromiseResult = result;
// 执行回调函数
this.callbacks.forEach((callback) => callback.onFulfilled(result));
}
});
};
// 将 reject 函数绑定到 Promise 实例上
this.reject = (error) => {
setTimeout(() => {
if(this.PromiseState === SelfPromise.PADDIBNG){
// 更新状态
this.PromiseState = SelfPromise.REJECT;
// 存储结果
this.PromiseResult = error;
// 执行回调函数
this.callbacks.forEach((callback) => callback.onRejected(result));
}
});
};
+
+
}
这样,顺序就对啦。
5、返回Promise对象
打印原生Promise
const P = new Promise((resolve,reject) => {
resolve("执行");
}).then(()=>{})
console.log(P); // Promise {<pending>}
打印手写Promise
const P = new SelfPromise((resolve,reject) => {
resolve("执行");
}).then(()=>{})
console.log(P); // undefined
所以我们知道then是要返回new SelfPromise对象的。所以这样改。
class SelfPromise {
constructor(){
+
+
then(onFulfilled, onRejected) {
return new SelfPromise((resolve, reject) => {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
onRejected = typeof onRejected === 'function' ? onRejected : () => {};
if(this.PromiseState === SelfPromise.PADDIBNG){
this.callbacks.push({
onFulfilled,
onRejected,
})
}
if(this.PromiseState === SelfPromise.FULILLED){
setTimeout(()=>{
onFulfilled(this.PromiseResult)
})
}
if(this.PromiseState === SelfPromise.REJECT){
setTimeout(()=>{
onRejected(this.PromiseResult)
})
}
})
}
+
+
}
再来看结果
const P = new SelfPromise((resolve,reject) => {
resolve("执行");
}).then(()=>{})
console.log(P);
// SelfPromise {PromiseState: '等待', PromiseResult: null, callbacks: Array(0), resolve: ƒ, reject: ƒ}
四、Promise链式操作
对原生Promise链式操作
const P = new Promise((resolve,reject) => {
resolve("执行");
}).then(
res => console.log(res,"then1"),
err => console.log(err)
).then(
res => console.log(res,"then2"),
err => console.log(err)
).then(
res => console.log(res,"then3"),
err => console.log(err)
)
// 结果
执行 then1
undefined 'then2'
undefined 'then3'
对手写Promise链式操作
const P = new Promise((resolve,reject) => {
resolve("执行");
}).then(
res => console.log(res,"then1"),
err => console.log(err)
).then(
res => console.log(res,"then2"),
err => console.log(err)
).then(
res => console.log(res,"then3"),
err => console.log(err)
)
// 结果
执行 then1
所以手写代码又有问题了,来看看是哪里问题。 通过大断点发现,有三个then,三个then都去执行了,但是resolve,却只执行了第一个,所以只有第一个then有结果,所以我们得让每个resolve都执行。会想到,因为我们的then任务是存起来的,存到了callbacks里面。但是resolve却没有执行,那我们把每个then的resolve也存到callbacks里面,不久可以调用了吗?所以我们将回调函数添加到 callbacks 数组中时候需要改造一下。得到下面代码:
class SelfPromise {
constructor(){
+
+
then(onFulfilled, onRejected) {
return new SelfPromise((resolve, reject) => {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
onRejected = typeof onRejected === 'function' ? onRejected : () => {};
if(this.PromiseState === SelfPromise.PADDIBNG){
this.callbacks.push({
+ onFulfilled: (result) => {
+ try {
+ // 如果没有传入成功回调函数,则将结果传递给下一个 MyPromise 对象
+ resolve(
+ typeof onFulfilled === "function"
+ ? onFulfilled(result)
+ : result
+ );
+ } catch (error) {
+ // 如果执行成功回调函数出现错误,则将错误传递给下一个 MyPromise 对象
+ reject(error);
+ }
+ },
+ onRejected: (error) => {
+ try {
+ // 如果没有传入失败回调函数,则将错误传递给下一个 MyPromise 对象
+ resolve(
+ typeof onRejected === "function" ? onRejected(error) : error
+ );
+ } catch (error) {
+ // 如果执行失败回调函数出现错误,则将错误传递给下一个 MyPromise 对象
+ reject(error);
+ }
},
})
}
if(this.PromiseState === SelfPromise.FULILLED){
setTimeout(()=>{
onFulfilled(this.PromiseResult)
})
}
if(this.PromiseState === SelfPromise.REJECT){
setTimeout(()=>{
onRejected(this.PromiseResult)
})
}
})
}
+
+
}
再来执行手写Promise。
const P = new SelfPromise((resolve,reject) => {
resolve("执行");
}).then(
res => console.log(res,"then1"),
err => console.log(err)
).then(
res => console.log(res,"then2"),
err => console.log(err)
).then(
res => console.log(res,"then3"),
err => console.log(err)
)
// 结果
执行 then1
undefined 'then2'
undefined 'then3'
到这里。手写Promise基础版本就完成啦。如果只是面对面试的话,你已经得了80分了,但是面试官可能让你写Promise的其他Api(race、all等),我们这先写好基础版本,接下来继续完善。
完整代码
class SelfPromise {
static PADDIBNG = "等待";
static FULILLED = "成功";
static REJECT = "拒绝";
constructor(executor) {
// 存储 Promise 状态
this.PromiseState = SelfPromise.PADDIBNG;
// 存储 Promise 结果
this.PromiseResult = null;
// 存储 Promise 回调函数
this.callbacks = [];
this.resolve = (result) => {
setTimeout(() => {
if(this.PromiseState === SelfPromise.PADDIBNG){
// 更新状态
this.PromiseState = SelfPromise.FULILLED;
// 存储结果
this.PromiseResult = result;
// 执行回调函数
this.callbacks.forEach((callback) => callback.onFulfilled(result));
}
});
};
// 将 reject 函数绑定到 Promise 实例上
this.reject = (error) => {
setTimeout(() => {
if(this.PromiseState === SelfPromise.PADDIBNG){
// 更新状态
this.PromiseState = SelfPromise.REJECT;
// 存储结果
this.PromiseResult = error;
// 执行回调函数
this.callbacks.forEach((callback) => callback.onRejected(result));
}
});
};
try {
// 执行器函数接受 resolve 和 reject 函数作为参数
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error)
}
}
then(onFulfilled, onRejected) {
return new SelfPromise((resolve, reject) => {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
onRejected = typeof onRejected === 'function' ? onRejected : () => {};
if(this.PromiseState === SelfPromise.PADDIBNG){
this.callbacks.push({
onFulfilled: (result) => {
try {
// 如果没有传入成功回调函数,则将结果传递给下一个 MyPromise 对象
resolve(
typeof onFulfilled === "function"
? onFulfilled(result)
: result
);
} catch (error) {
// 如果执行成功回调函数出现错误,则将错误传递给下一个 MyPromise 对象
reject(error);
}
},
onRejected: (error) => {
try {
// 如果没有传入失败回调函数,则将错误传递给下一个 MyPromise 对象
resolve(
typeof onRejected === "function" ? onRejected(error) : error
);
} catch (error) {
// 如果执行失败回调函数出现错误,则将错误传递给下一个 MyPromise 对象
reject(error);
}
},
})
}
if(this.PromiseState === SelfPromise.FULILLED){
setTimeout(()=>{
onFulfilled(this.PromiseResult)
})
}
if(this.PromiseState === SelfPromise.REJECT){
setTimeout(()=>{
onRejected(this.PromiseResult)
})
}
})
}
catch(onRejected) {
// 调用 then 方法,并将 onRejected 函数作为第二个参数传入
return this.then(null, onRejected);
};
}
对于手写代码,如果没有写过的话,着实挺费劲,但是,当你看过几遍,手写几遍之后,你就会发现,这个太简单了吧,而且经常手写这些有些代码你会得到质的提升,所以要加油。所以还是那句话,没有牛逼的程序员,只有勤劳的程序员。
最后撒花 🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉