某日下班回家,自己突然心血来潮,想重写下Promise,这就上手了。
首先来看下promise的使用
let promise = new Promise(function(resolve,reject) {
if(true){
resolve(value)
}else{
reject(error)
}
})
promise.then(function(res) {
}).catch(function(err) {
}).finally(function(e){
})
由使用方式我们可以知道:
1.Promise本是一个构造函数,构造函数内必传一个参数,且类型为函数
2.该函数自带两个参数,均为函数,思路是使用bind将参数注入
3.Promise实例有三个方法,为then,catch,finally
4.then和catch在resolve或reject时分别触发
5.then,catch,finally也需传函数,且前两者参数分别为resolve及reject所传,则需将resolve及reject所传参数注入到实例中
6.then和catch可以链式调用,证明其返回实例this
7.promise三个实例函数为异步调用,此处决定使用setTimeout做异步操作,但是还是有区别的,参考js异步的微任务和宏任务。
经测试,触发catch情况有两种:
1.手动调用reject
2.promise传入的函数参数抛出错误
话不多说,上代码
let myPromise = function (fn) {
this["[[PromiseStatus]]"];
this["[[PromiseValue]]"];
if (typeof fn === "function") {
try {
fn.call(null, arguments.callee.resolve.bind(this), arguments.callee.reject.bind(this))
} catch (error) {
arguments.callee.reject.call(this, error)
}
} else {
throw new Error("Promise resolver undefined is not a function")
}
}
// 测试resolve果然存在
// console.log(Promise.resolve) //ƒ resolve() { [native code] } ,证明resolve和reject函数存为
// Promise的静态方法
myPromise.resolve = function (value) {
this["[[PromiseStatus]]"] = "resolved";
//存resolve参数
this["[[PromiseValue]]"] = value;
}
myPromise.reject = function (err) {
this["[[PromiseStatus]]"] = "rejected";
//存reject参数
this["[[PromiseValue]]"] = err;
}
// 原型上的方法
//使用Object.defineProperties是为了符合Promise实例的几个函数不可枚举
Object.defineProperties(myPromise.prototype, {
"then": {
value: function (fn) {
//异步
setTimeout(() => {
if (typeof fn === "function") {
if (this["[[PromiseStatus]]"] === "resolved") {
fn.call(null, this["[[PromiseValue]]"])
}
}
}, 0)
//链式调用
return this
},
enumerable: false
},
"catch": {
value: function (fn) {
setTimeout(() => {
if (typeof fn === "function") {
if (this["[[PromiseStatus]]"] === "rejected") {
fn.call(null, this["[[PromiseValue]]"])
throw new Error("Uncaught (in promise)" + this["[[PromiseValue]]"])
}
}
}, 0)
//链式调用
return this
},
enumerable: false
},
"finally": {
value: function (fn) {
setTimeout(() => {
if (typeof fn === "function") {
fn()
}
}, 0)
},
enumerable: false
},
})
下面来测试我们写的Promise
let fn = function (resolve, reject) {
if (2 > 1) {
resolve("666")
} else {
reject("错了哦")
}
// if (2 < 1) {
// resolve("666")
// } else {
// reject("错了哦")
// }
// throw new Error("传入函数报错了")
}
let promise = new myPromise(fn)
console.log(promise)
promise.then("怎么说")
promise.then(res => {
console.log("执行then", res)
}).catch(err => {
console.log("执行catch", err)
})
上面尝试给then方法传了一个字符串,也是如原生Promise一样并没有输出任何内容。
上面实现Promise方式为函数做类,后续如果有时间说不定会写个es6 class的版本。