为什么Promise构造函数需要执行程序?

时间:2016-06-06 07:28:44

标签: javascript asynchronous promise w3c

使用Promises时,为什么不能在代码库的其他地方定义resolvereject的触发器?

我不明白为什么resolvereject逻辑应该在声明promise的位置进行本地化。这是疏忽,还是强制要求executor参数?

我认为执行函数应该是可选的,并且它的存在应该确定promise是否封装了解决方案。如果没有这样的要求,承诺将更加可扩展,因为您不必立即启动异步。承诺也应该是可以重置的。它是1个开关,1或0,resolve()reject()。可附加多个并行和顺序结果:promise.then(parallel1)promise.then(parallel2)以及promise.then(seq1).then(seq2)但参考特权玩家无法解析/拒绝INTO切换

你可以在以后构建一个结果树,但是你不能改变它们,也不能改变根(输入触发器)

老实说,顺序结果的树也应该是可编辑的......假设你想要拼出一个步骤并在你宣布许多承诺链之后做其他事情。重建承诺和每个顺序功能都没有意义,特别是因为你甚至不能拒绝或摧毁承诺...

2 个答案:

答案 0 :(得分:12)

这被称为由Domenic创造的the revealing constructor pattern

基本上,我们的想法是让您访问对象的部分,而该对象尚未完全构建。引用Domenic:

  

我称之为揭示构造函数模式,因为Promise构造函数正在揭示其内部功能,但仅限于构造相关承诺的代码。解决或拒绝承诺的能力仅在构造代码中显示,并且对于使用承诺的任何人来说都是至关重要的。因此,如果我们将p交给另一个消费者,请说

过去

最初,promises使用延迟对象,这在JavaScript承诺的Twisted promises中也是如此。在Angular的$q,Q,jQuery和旧版本的旧版本中,这仍然是正确的(但经常被弃用)。蓝鸟。

API类似于:

var d = Deferred();
d.resolve(); 
d.reject();
d.promise; // the actual promise

它有效,但它有问题。 Deferreds和promise构造函数通常用于将非承诺API转换为promise。 JavaScript中存在一个名为Zalgo的“着名”问题 - 基本上,它意味着API必须是同步的或异步的,但不能同时进行。

事情是 - 通过延迟,可以做类似的事情:

function request(param) {
   var d = Deferred();
   var options = JSON.parse(param);
   d.ajax(function(err, value) { 
      if(err) d.reject(err);
      else d.resolve(value);
   });
}

这里有一个隐藏的细微错误 - 如果param不是一个有效的JSON,这个函数会同步抛出,这意味着我必须在{{1}中包装每个promise返回函数并且} catch (e) {可以捕获所有错误。

promise构造函数捕获此类异常并将其转换为拒绝,这意味着您永远不必担心同步异常与使用promises的异步异常。 (它通过在下一个勾号中始终执行.catch(e =>回调来保护你的另一方。)

此外,它还需要一个额外的类型,每个开发人员必须了解promise构造函数不适合的地方。

答案 1 :(得分:4)

仅供参考,如果您仍然希望使用延迟接口而不是Promise执行器接口,尽管有很好的理由反对延迟接口,您可以轻松编码一次,然后在任何地方使用它(我个人认为这是个坏主意)以这种方式编码,但是你对这个主题的问题表明你的思维方式不同,所以这里是:)

function Deferred() {
    var self = this;
    var p = this.promise = new Promise(function(resolve, reject) {
        self.resolve = resolve;
        self.reject = reject;
    });
    this.then = this.promise.then.bind(p);
    this.catch = this.promise.catch.bind(p);
}

现在,您可以使用您似乎要求的界面:

var d = new Deferred();
d.resolve(); 
d.reject();
d.promise;     // the actual promise
d.then(...)    // can use .then() on either the Deferred or the Promise
d.promise.then(...)

这是一个稍微紧凑的ES6版本:

function Deferred() {
    let p = this.promise = new Promise((resolve, reject) => {
        this.resolve = resolve;
        this.reject = reject;
    });
    this.then = this.promise.then.bind(p);
    this.catch = this.promise.catch.bind(p);
}

或者,您可以使用此Deferred()构造函数执行您在问题中要求的内容:

var request = new Deferred();
request.resolve();
request.then(handleSuccess, handleError);

但是,它有本杰明指出的缺点,并不被认为是编码承诺的最佳方式。

显示类似的内容here on MDN