阅读 75

promise基本实现思路

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方法的函数参数保存起来就已经调用了,那么如何实现异步呢?

js提供四种实现异步的定时器机制

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如何实现,下次更新。

文章分类
前端