promise是用来解决疯狂地狱式回调函数的问题,多种嵌套回调函数的方式不利于代码的维护,于是是否可以让回调函数不用嵌套,按照同步的方式来写
先看一段promise函数的简单代码的应用:
new Promise(function(resolve, reject) {
console.log('init');
resolve('then1');
}).then(function(val) {
console.log(val);
return "then2";
}).then(function(val) {
console.log(val);
})
结果:
init
then1
then2
复制代码
分析:
1.根据promise的构造函数来看,只有调用resolve方法后,才会执行then后面的函数
2.then方法可以链式调用,上一层的then函数返回值可以传给下一层的函数then的参数
猜想:
当调用resolve方法后,then后面的函数是依次执行的,then函数可能是会将传入的函数参数保存到内部数组去,但是为了确保在resolve之后,then所有的函数参数都已经保存起来,resolve方法执行顺序可能是异步的;可能还会存在一个保存then函数之间传递的内部参数值。
下面写个简单实例来探究:
function MPromise(fn) {
this.thenCb = [];
this.state = null;
this.value = null;
fn(this.resolve, this.reject, this);
}
MPromise.prototype.then = function(onResolve, onReject) {
this.thenCb.push(onResolve);
return this;
}
MPromise.prototype.resolve = function(_value, self) {
setTimeout(() => {
self.value = _value;
for (var i = 0; i < self.thenCb.length; i++) {
self.value = self.thenCb[i](self.value);
}
}, 0);
}
var p = new MPromise((resolve, reject, self) => {
console.log('init');
resolve('then1', self);
}).then(val => {
console.log(val);
return 'then2'
}).then(val => {
console.log(val);
});
结果:
init
then1
then2
复制代码
似乎这个已经可以实现当前的功能了。细究一下resolve方法必须是异步的,否则还没等到将then方法的函数参数保存起来就已经调用了,那么如何实现异步呢?
setTimeout;setImmediate;Process.nextTick
setImmediate和Process.nextTick的区别
A(); B(); C(); ------------------------------------------------------------------------A(); process.nextTick(B); C(); ------------------------------------------------------------------------A(); setImmediate(B); C();
process.nextTick:在本轮循环结束后立刻执行,相当于微任务
setImmediate:在次轮循环开始最后才执行,相当于宏任务
参考:事件循环队列
所以一般在低版本ie8浏览器下,选择使用setTimeout来实现异步。
言归正传:知道如何实现异步之后,如果then函数返回是一个新的promise,该如何区分执行
promise源码中
// States:
//
// 0 - pending
// 1 - fulfilled with _value
// 2 - rejected with _value
// 3 - adopted the state of another promise, _value
//
// once the state is no longer pending (0) it is immutable
复制代码
promise状态一旦改变就不可以更改,并且只允许从0 -> 1/2/3,界定每个promise的状态值来解决
还有reject, catch, promise.all, promise.race如何实现,下次更新。