稍后在Promise上添加附加条款

时间:2019-11-28 11:15:42

标签: javascript ecmascript-6

我是Java和Promise的新手。我可以理解Promise何时立即具有on子句,如下:

//example 1
var promise1 = new Promise(function(resolve, reject) {
  console.log("Hi")
  resolve("World")
}).then(function(value) {
  console.log(value);
});

但是如果then子句在单独的语句中为:

//example 2
var promise1 = new Promise(function(resolve, reject) {
  console.log("Hi")
  resolve("World")
});

 //at time t here

promise1.then(function(value) {
  console.log(value);
});

console.log("Hello");

那我有点困惑,因为从技术上讲,时间t之前的语句已经执行,并且当resolve("World")被调用时,因为没有then子句被“注册”,所以什么也不会发生。在时间t之后,promise1.then(...)执行,并且它不应该知道已经调用了resolve("World")。但是实际输出确实表明它知道resolve("World")已被调用。

那么这是否意味着编译器确实在此提供帮助?例如,编译器像示例1一样在promise1语句之后合并then子句?

2 个答案:

答案 0 :(得分:3)

这是因为Promise对象在内部保持其状态。 因此,当您在Promise对象上调用.then时,它将:

  • 等待解决,然后触发回调
  • 如果承诺已经解决,则回调将立即执行

答案 1 :(得分:1)

  

那么这是否意味着编译器确实在此提供帮助?例如,编译器像示例1一样在promise1语句之后合并then子句?

不,发生的魔术比您想象的要少得多。 new Promise返回一个Promise对象。一个Promise对象有一个.then方法。您可以使用此方法告诉一旦被解决的承诺,调用传递的函数。 Promise对象会保留此回调。

您可以将其视为注册事件处理程序。一旦发生“解决事件”,该函数就会执行。

当然,承诺者会知道它是否已解决。因此,如果在已解决的Promise上调用.then,它可以立即安排回调的调用。

这是一个非常贫穷的人对诺言的执行(不处理拒绝和其他事情),这可能使您更好地了解诺言的工作方式。请注意,我在这里使用setTimeout来模拟promise如何总是在event loop的下一个滴答处执行回调,但是实际上JavaScript使用了其他一些内部API:

class Promise {
  constructor(handler) {
    this._callbacks = [];
    // Execute the passed handler, passing the "resolve" function
    handler(value => {
      // Mark the promise as resolved
      this._resolved = true;
      // Remember the value
      this._value = value;
      // Execute all registered callbacks
      this._callbacks.forEach(cb => cb(value));
    });
  }
  
  then(handler) {
    let _resolve;
    const promise = new Promise(resolve => _resolve = resolve);
    const callback = value => {    
      setTimeout(
        () => _resolve(handler(value)),
        0
      );
    };
    
    // Is the promise already resolved?
    if (this._resolved) {
      // Immediately schedule invocation of handler with the remembered value
      callback(this._value);
    } else {
      // Remember callback for future invocation
      this._callbacks.push(callback);
    }
    
    return promise;
  }
}

const promise = new Promise(resolve => {
  console.log('inside Promise');
  resolve(42);
});

console.log('in between');

promise.then(v => {
  console.log('inside then', v);
})

promise.then(v => {
  console.log('inside another then', v);
  return 21;
})
.then(v => {
  console.log('.then returns a new promise', v);
});