前言:用过Promise的前端小伙伴都应该对它的API语法很熟悉了,这里我就不详细说了,我们直接上代码吧!
- 1.首先我们知道在new Promise创建一个新实例的时候,如果什么都不传的时候会报错的
那么我们首先做一个参数合法校验。
function Promise(executor) {
// 参数合法校验
if (typeof executor !== "function") {
throw new TypeError("Promise resolve " + executor + " is not a function");
}
}
- 2.我们知道promise有3个状态,fulfilled(成功),rejected(失败),pending(等待态).一旦状态成功就不能失败,一旦失败就不可能成功,当状态为等待态的时候,可能成功,也可能失败。
- 3.每一个Promise实例我们一般常用的有3个方法,then,catch,all 下面我们将一个简单的Promise框架搭成这个样子
function Promise(executor) {
// 参数合法校验
if (typeof executor !== "function") {
throw new TypeError("Promise resolve " + executor + " is not a function");
}
// 设置实例的私有属性
this.PromiseStatus = "pending"; // 初始状态下设置该Promise的状态为等待态
this.PromiseValue = undefined;
// 设定传递给executor并且执行可以修改实例状态和value的resolve/reject的函数
// new Promise的时候会立即把executor这个函数执行
// executor函数执行出现错误,也会把实例的状态改为失败,且value是失败的原因
try {
executor(function resolve(value) {
},function reject(reason) {
});
} catch (err) {
reject(err.message);
}
}
// 定义在Promise原型上的方法是共有属性
Promise.prototype.then = function () {}
Promise.prototype.catch = function () {}
new Promise(function (resolve,reject){
reject(100);
});
我们的框架就这么搭好啦哈哈哈哈!
我们来写一个公共方法来修改实例的状态和值
// 修改实例的状态和值,将方法中的this改为实例,只有当前状态为pending才能修改状态
var _this = this;
function change(status,value) {
if (_this.PromiseStatus !=== "pending") return;
_this.PromiseStatus = status;
_this.PromiseValue = value;
}
try {
executor(function resolve(value) {
change("fulfilled",value);
},function reject(reason) {
change("rejected",reason);
});
} catch (err) {
change("rejected",err.message);
}
- 接下来我们new一个Promise实例,就可以实现一个简单Promise效果
// 在浏览器里面试试,返回一个rejecyed状态,值为100
var p1 = new Promise(function (resolve,reject){
reject(100);
});
下面来思考一下then方法
p1.then(function (value) {
console.log("OK",value);
},function (reason) {
console.log("NO",reason);
});
console,log(p1);
// 我们发现我们手写的Promise确实把状态和值改掉了,但是没有执行.then这个方法
我们需要通知.then的方法执行后才去执行resolve/reject方法,这里我们先要注入.then方法
this.resolveFunc = function() {};
this.rejectFunc = function() {};
function change(status,value) {
if (_this.PromiseStatus !=== "pending") return;
_this.PromiseStatus = status;
_this.PromiseValue = value;
//注入.then方法(异步的)
var delayTimer = setTimeout(function () {
clearTimeout(delayTimer);
delayTimer = null;
var status = _this.PromiseStatus,value = _this.PromiseValue;
status === "fulfilled"?_this.resolveFunc.call(_this,value) :
_this.rejectFunc.call(_this,value);
},0);
}
Promise.prototype.then = function (resolveFunc,rejectFunc) {
this.resolveFunc = resolveFunc;
this.rejectFunc = rejectFunc;
}
下面我们来优化一下.then这个方法
- .then 这个方法可以穿一个函数,也可以传两个函数。传一个函数就把成功或者失败的函数顺延到下一个.then的方法里。
Promise.prototype.then = function (resolveFunc,rejectFunc) {
// 参数不传默认值的处理,实现状态的顺延
if (typeof resolveFunc !== "function") {
resolveFunc = function(value) {
return Promise.resolve(value); // 返回一个成功的顺延
}
}
if (typeof rejectFunc !== "function") {
rejectFunc = function(reason) {
return Promise.reject(reason); // 返回一个失败的顺延
}
}
var _this = this;
// this.resolveFunc = resolveFunc;
// this.rejectFunc = rejectFunc;
// 返回一个新的Promise实例
return new Promise(function (resolve,reject) {
// 我们返回的新实例的成功和失败
_this.resolveFunc = function (value) {
try {
var x = resolveFunc.call(_this,value);
x instanceof Promise?x.then(resolve,reject):resolve(x);
} catch (err) {
reject(err.message);
}
}
_this.rejectFunc = function (reason) {
try {
var x = rejectFunc.call(_this,reason);
x instanceof Promise?x.then(resolve,reject):resolve(x); // 只要执行不报错,返回的都是成功
} catch (err) {
reject(err.message);
}
}
});
}
// 把Promise当做一个对象,在这个对象上写这两个方法
Promise.resolve = function (value) {
return new Promise(function(resolve) {
resolve(value);
});
}
Promise.reject = function () {
return new Promise(function(_,reject) {
reject(reason);
});
}
接着写.catch方法
Promise.prototype.catch = function (rejectFunc) {
return this.then(null,rejectFunc);
}
接着写.all方法
Promise.all = function(promiseArr) {
return new Promise(function(resolve, reject) {
var index = 0, values = [];
for (var i = 0;i < promiseArr.length; i++) {
// 利用闭包的方式保存循环的每一项索引
(function (i) {
var item = promiseArr[i];
// 当前项不是Promise,直接当成成功项
!(item instanceof Promise)?item=Promise.resolve(item):null;
// 如果当前项是Promise
item.then(function (value) {
index++;
values[i] = value;
if (index >= promiseArr.length) {
resolve(values); // 所有的实例都是成功的
}
}).catch(function (reason) {
// 一个失败,全部失败
reject(reason);
});
})(i);
}
})
}
到这里,最简单的Promise是实现了。End~^_^