Promise的手写
Javascript
-
首先定义一个Promise的方法,名称任意,传入执行器
executor// 传入执行器 executor function rfxyPromise(executor) { function resolve() { console.log("resolve") } function reject() { console.log("reject") } executor(resolve,reject) } -
调用该Promise方法
var p = new rfxyPromise((resolve, reject) => { resolve("调用resolve方法") //reject("调用reject方法") }) p.then((res) => { console.log(res) }, (err) => { console.log(err) }) -
设置rfxyPromise函数的
then//这个方法仅让浏览器不进行报错 rfxyPromise.prototype.then = function () { } -
设置
fulfilled值和pending值 function rfxyPromise(executor) { //初始的 status 值为 pending this.status = "pending" function resolve() { //谁调用this,this就指向谁 //结果显示,此处的this指向的是window console.log(this) //设置status为执行后的结果 this.status = "fulfiled" } function reject() { //设置status为执行后的结果 this.status = "rejected" } executor(resolve,reject) } -
设置一个局部的
this保存 thisfunction rfxyPromise(executor) { this.status = "pending" var _this = this function resolve() { console.log(_this) _this.status = "fulfiled" } function reject() { _this.status = "rejected" } executor(resolve,reject) } -
为
then添加方法rfxyPromise.prototype.then = function (successCB,failCB) { //检验返回的是否为 fulfilled 或 rejected,从而决定执行那一步 if (this.status === "fulfilled") { successCB() } else if (this.status === "rejected"){ failCB() } } -
定义
resfunction rfxyPromise(executor) { this.status = "pending" var _this = this //设置result为undefined //result用于存储函数的参数,供successCB和failCB使用 var _result = undefined function resolve(res) { console.log(_this) _this.status = "fulfilled" _this.result = res } function reject(res) { _this.status = "rejected" _this.result = res } executor(resolve,reject) } -
传送
resultrfxyPromise.prototype.then = function (successCB,failCB) { if (this.status === "fulfilled") { successCB(this.result) } else if (this.status === "rejected"){ failCB(this.result) } } -
优化细节
//删掉err传递的错误函数,再删掉res的成功函数,验证是否可以成功 p.then(res => { console.log("success", res) }) //此处加入判断条件是否成立,决定程序是否会进行报错 rfxyPromise.prototype.then = function (successCB, failCB) { if (this.status === "fulfilled") { //验证原型上 .then 中的回调函数是否为真,决定是否能运行 successCB && successCB(this.result); } else if (this.status === "rejected") { //验证原型上 .then 中错误的回调函数是否为真,决定是否能运行 failCB && failCB(this.result); } }; -
保持
fulfilled和rejected不会被替代function rfxyPromise(executor) { this.status = "pending"; var _this = this; var _result = undefined; function resolve(res) { if (_this.status !== "pending") {return;} _this.status = "fulfilled"; _this.result = res; } function reject(res) { if (_this.status !== "pending") {return;} _this.status = "rejected"; _this.result = res; } executor(resolve, reject); } -
设置一个定时器,用于模拟Ajax请求方式
var p = new rfxyPromise((resolve, reject) => { setTimeout(() => { resolve("111") }, 1000) // reject("32") }) //此时的 .then 方法不会执行,因为当前是 pending 状态,和下面代码没有关系 rfxyPromise.prototype.then = function (successCB, failCB) { if (this.status === "fulfilled") { successCB(this.result); } if (this.status === "rejected") { failCB && failCB(this.result); } //验证状态:输出pending console.log(this.status) }; -
收集回调
rfxyPromise.prototype.then = function (successCB, failCB) { if (this.status === "fulfilled") { successCB(this.result); } if (this.status === "rejected") { failCB && failCB(this.result); } //将回调函数收集在cb中 if (this.status === "pending") { this.cb = { successCB, failCB, }; } }; -
在Promise方法中添加刚设置的
cbfunction rfxyPromise(executor) { this.status = "pending"; this.result = undefined; //此处收集回调函数 this.cb = {}; var _this = this; function resolve(res) { if (_this.status !== "pending") { return; } _this.status = "fulfilled"; _this.result = res; //将成功函数调用 _this.cb.successCB &&_this.cb.successCB() } function reject(res) { if (_this.status !== "pending") { return; } _this.status = "rejected"; _this.result = res; //将失败函数调用 _this.cb.failCB &&_this.cb.failCB() } executor(resolve, reject); } -
将值传递给回调函数,
res和req就可以使用了( 此过程类似于订阅发布模式)function rfxyPromise(executor) { this.status = "pending"; this.result = undefined; this.cb = {}; var _this = this; function resolve(res) { if (_this.status !== "pending") { return; } _this.status = "fulfilled"; _this.result = res; //添加_this.result _this.cb.successCB &&_this.cb.successCB(_this.result) } function reject(res) { if (_this.status !== "pending") { return; } _this.status = "rejected"; _this.result = res; //添加_this.result _this.cb.failCB &&_this.cb.failCB(_this.result) } executor(resolve, reject); } -
在
.then中,异步编程将会覆盖回调函数,回调函数中的cb是对象,所以改为使用数组,压栈!function rfxyPromise(executor) { this.status = "pending"; this.result = undefined; //修改为数组 this.cb = []; var _this = this; function resolve(res) { if (_this.status !== "pending") { return; } _this.status = "fulfilled"; _this.result = res; _this.cb.successCB &&_this.cb.successCB(_this.result) } function reject(res) { if (_this.status !== "pending") { return; } _this.status = "rejected"; _this.result = res; _this.cb.failCB &&_this.cb.failCB(_this.result) } executor(resolve, reject); } rfxyPromise.prototype.then = function (successCB, failCB) { if (this.status === "fulfilled") { successCB(this.result); } if (this.status === "rejected") { failCB && failCB(this.result); } if (this.status === "pending") { //用push方法进行压栈操作 this.cb.push({ successCB, failCB }); } }; -
遍历每一个数组
function rfxyPromise(executor) { this.status = "pending"; this.result = undefined; this.cb = []; var _this = this; function resolve(res) { if (_this.status !== "pending") { return; } _this.status = "fulfilled"; _this.result = res; //使用forEach进行遍历 _this.cb.forEach(item => { item.successCB && item.successCB(_this.result) }) } function reject(res) { if (_this.status !== "pending") { return; } _this.status = "rejected"; _this.result = res; //使用forEach进行遍历 _this.cb.forEach(item => { item.failCB &&item.failCB(_this.result) }) } executor(resolve, reject); }