现在es6的promise已经是用的很广泛的,可以有效的解决地域回调的问题。
那么现在我们可以制作一个简单的promise,让自己更加熟悉promise。
一.回顾promise
先我们需要了解一下promise的用法。以下demo
var p=new Promise(function(resolve,reject){
setTimeout(function(){
resolve("success")
},1000);
console.log("创建一个新的promise");
})
p.then(function(x){
console.log(x)
})
//输出:
创建一个新的promise
success
以上就是一个promise的实例。从上述例子可以看出,promise可以处理异步操作。此外还可以链式调用
二.了解一下promise规范https://promisesaplus.com/
我们主要关心它的要求有一下几点:
1.一个promise必须有3个状态,pending,fulfilled(resolved),rejected当处于pending状态的时候,可以转移到fulfilled(resolved)或者rejected状态。当处于fulfilled(resolved)状态或者rejected状态的时候,就不可变。
2.一个promise必须有一个then方法,then方法接受两个参数:
3.为了实现链式调用,then方法必须返回一个promise
三.制作promise
接下来我们来制作简单的promise,以下将分几个版本,来循序渐进的增加内容
1) v1.0版本
function myPromise(constructor){
let self=this;
self.status="pending" //定义状态改变前的初始状态
self.value=undefined;//定义状态为resolved的时候的状态
self.reason=undefined;//定义状态为rejected的时候的状态
function resolve(value){
//两个==="pending",保证了状态的改变是不可逆的
if(self.status==="pending"){
self.value=value;
self.status="resolved";
}
}
function reject(reason){
//两个==="pending",保证了状态的改变是不可逆的
if(self.status==="pending"){
self.reason=reason;
self.status="rejected";
}
}
//捕获构造异常
try{
constructor(resolve,reject);
}catch(e){
reject(e);
}
}
同时在原型链上增加then方法
myPromise.prototype.then=function(onFullfilled,onRejected){
let self=this;
switch(self.status){
case "resolved":
onFullfilled(self.value);
break;
case "rejected":
onRejected(self.reason);
break;
default:
}
}
然后测试一下
var p=new myPromise(function(resolve,reject){resolve(1)});
p.then(function(x){console.log(x)})
//输出1
但是我们可以发现这边是没有异步过程的,即then里面是没有处理内容的
v1.1
增加异步功能
function myPromise(constructor){
let self=this;
self.status="pending" //定义状态改变前的初始状态
self.value=undefined;//定义状态为resolved的时候的状态
self.reason=undefined;//定义状态为rejected的时候的状态
self.onFullfilledArray=[];
self.onRejectedArray=[];
function resolve(value){
if(self.status==="pending"){
self.value=value;
self.status="resolved";
self.onFullfilledArray.forEach(function(f){
f(self.value);
//如果状态从pending变为resolved,
//那么就遍历执行里面的异步方法
});
}
}
function reject(reason){
if(self.status==="pending"){
self.reason=reason;
self.status="rejected";
self.onRejectedArray.forEach(function(f){
f(self.reason);
//如果状态从pending变为rejected,
//那么就遍历执行里面的异步方法
})
}
}
//捕获构造异常
try{
constructor(resolve,reject);
}catch(e){
reject(e);
}
}
myPromise.prototype.then=function(onFullfilled,onRejected){
let self=this;
switch(self.status){
case "pending":
self.onFullfilledArray.push(function(){
onFullfilled(self.value)
});
self.onRejectedArray.push(function(){
onRejected(self.reason)
});
break;
case "resolved":
onFullfilled(self.value);
break;
case "rejected":
onRejected(self.reason);
break;
default:
}
}
现在在来测试已经可以发出then了
但是现在还无法处理链式调用then
v1.3
增加then链式调用
v1.3.1
最简单的就是then返回一个对象,可以进行链式调用
myPromise.prototype.then=function(onFullfilled,onRejected){
let self=this;
switch(self.status){
case "pending":
self.onFullfilledArray.push(function(){
onFullfilled(self.value)
});
self.onRejectedArray.push(function(){
onRejected(self.reason)
});
break;
case "resolved":
onFullfilled(self.value);
break;
case "rejected":
onRejected(self.reason);
break;
default:
}
return this
}
一个简单的this就是promise对象本身,这样就可以了,按时this永远都是同一个promise对象,即then里的value永远都是相同的
因此我们需要返回一个新的promise
v1.3.2
promise.prototype.then = function(onFullfilled, onRejected) {
var self = this
let promise2
switch (self.status) {
case "pending":
promise2 = new promise(function(resolve, reject) {
self.onFullfilledArray.push(function() {
try {
let temple = onFullfilled(self.value)
resolve(temple)
} catch (e) {
reject(e)
}
})
self.onRejectedArray.push(function() {
try {
let temple = onRejected(self.reason);
resolve(temple)
} catch (e) {
reject(e) // error catch
}
})
})
break;
case "resolved":
promise2 = new promise(function(resolve, reject) {
try {
let temple = onFullfilled(self.value);
//将上次一then里面的方法传递进下一个Promise的状态
resolve(temple);
} catch (e) {
reject(e); //error catch
}
})
break;
case "rejected":
promise2 = new promise(function(resolve, reject) {
try {
let temple = onRejected(self.reason);
//将then里面的方法传递到下一个Promise的状态里
resolve(temple);
} catch (e) {
reject(e);
}
})
break;
default:
}
return promise2;
}
至此简单的promise已经完成了。但是这个promise还是有不少问题的,如then里面直接使用primise等。这些都是优化问题。
我们这样就知道了promise的运行机制了。
觉得不错的请点赞,谢谢。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。