JS 来实现一个 Promise
promise A+ 规范简述
- 一个promise必须有3个状态,pending,fulfilled(resolved),rejected当处于pending状态的时候,可以转移到fulfilled(resolved)或者rejected状态。当处于fulfilled(resolved)状态或者rejected状态的时候,就不可变。
- 一个promise必须有一个then方法,then方法接受两个参数,resolve和reject
- 实现链式调用,then方法必须返回一个promise
promise A+ 源码
Promise 源码:https://github.com/then/promise/blob/master/src/core.js
一个简单的实现
// this promise code refered to this blog
// http://www.cnblogs.com/liuzhenwei/p/5235473.html
var Promise = function (fn) {
var state = 'pending';
var doneList = [];
var failList= [];
this.then = function(done ,fail){
switch(state){
case 'pending':
doneList.push(done);
//每次如果没有推入fail方法,我也会推入一个null来占位
failList.push(fail || null);
return this;
break;
case 'fulfilled':
done();
return this;
break;
case 'rejected':
fail();
return this;
break;
}
}
function tryToJson(obj) {
var value;
try {
value = JSON.parse(obj);
} catch (e) {
value = obj;
}
return value
}
function resolve(newValue){
state = 'fulfilled';
setTimeout(function(){
var value = tryToJson(newValue);
for (var i = 0; i < doneList.length; i++){
var temp = doneList[i](value);
if (temp instanceof Promise) {
var newP = temp;
for (i++; i < doneList.length; i++) {
newP.then(doneList[i], failList[i]);
}
} else {
value = temp;
}
}
}, 0);
}
function reject(newValue){
state = 'rejected';
setTimeout(function(){
var value = tryToJson(newValue);
var tempRe = failList[0](value);
//如果reject里面传入了一个promise,那么执行完此次的fail之后,将剩余的done和fail传入新的promise中
if(tempRe instanceof Promise){
var newP = tempRe;
for (i=1;i<doneList.length;i++) {
newP.then(doneList[i],failList[i]);
}
} else {
//如果不是promise,执行完当前的fail之后,继续执行doneList
value = tempRe;
doneList.shift();
failList.shift();
resolve(value);
}
}, 0);
}
fn(resolve,reject);
}
其实是把then方法里的回调函数分别推入doneList和failList中,然后在promiFn执行完毕后开始调用 function resolve(newValue){} 里更改state状态为fulfilled并且执行doneListi;
var promiFn = function (resolve, reject) {
setTimeout(function () {
resolve(1)
}, 0)
};
new Promise(promiFn)
.then(function (d) {
console.log(d)
}, function (e) {
console.log(e);
})
promise 链式调用
let bodyToJson = null;
request('http:www.baidu.com')
.then((d) => {
return otherPromise;
})
.then((d) => {
return anotherPromise
})
.then((d) => {
// ...
})
.catch((err) => {
// ...
});
还缺的 API
- Promise.all
- Promise.race
- Promise.prototype.catch
- Promise.prototype.finally
等待完善。
问题:为什么 promise 需要引入微任务
Promise 中的执行函数是同步进行的,但是里面存在着异步操作,在异步操作结束后会调用 resolve 方法,或者中途遇到错误调用 reject 方法,这两者都是作为微任务进入到 EventLoop 中。但是你有没有想过,Promise 为什么要引入微任务的方式来进行回调操作?
若 promise 回调放在进行宏任务队列的队尾,若队列非常长,那么回调迟迟得不到执行,造成的效果就是应用卡顿。所以就引入了微任务。