将JavaScript的ES6承诺支持“做”的API?

例如

p = new Promise(function (resolve, reject) { throw 'err'; }); p.done(); 

在大多数承诺的polyfill库中,done会抛出一个错误,并且当前的执行会退出。

但是,如果我们使用p.then() ,什么都不会发生。 这个错误被诺言吞噬了。 如果我们使用p.catch ,我们无法退出当前的执行。 我想实现这样的事情:

 try { // something } catch (err) { if (check(err)) { throw err; } } 

没有。

在未来版本的规范中,不仅可能不被支持 – 它是不需要的。 引用Mariusz的链接:

Domenic:

它仍然是错误的倾向:如果你滑倒,甚至不遵守规则,你可能会永远沉默一个错误。

马克·米勒(谁是诺言的先驱者):

请注意,在ES7中,弱引用将为我们提供弥合这一差距所需的诊断工具之一。 使用弱引用,如果被拒绝的承诺在没有通知任何处理程序的情况下被收集,我们可以安排这生成一个诊断。 承诺实现必须将原因保留在承诺的执行者(验尸gc处理程序)中,以便在发现承诺已被拒绝后具有诊断报告。

Yehuda Kats RSVP的error handling程序:

我们在RSVP中采用的方法是安装默认抛出的未处理的承诺监视器。

如果您知道您将附加asynchronouserror handling程序,则可以通过附加noop失败处理程序来select此行为中的特定承诺。 我们可能会为此加糖(.undone:p)

根据我们的经验,将每个人的负担转移到可能要附加asynchronouserror handling程序的人是合适的。

而且,从规格之前的实际回购,多梅尼克说:

完成工作将通过将未处理的拒绝跟踪function集成到开发工具中来完成。 从我所了解的大多数TC39人以及我自己都认为足够完整的规范。


规格委员会不仅没有忽视,他们认为这是没有必要的,而且容易出错。 新的现代承诺库自动检测未处理的拒绝 – 这两个例子是当承诺和蓝鸟承诺开创了这个想法。

.done是一个神器 – 起源于浏览器无法检测到未处理的拒绝。 事实是 – 确定性地检测它们是不可能的,但对绝大多数情况来说,这是完全可能的。

不要相信我? 打开Firefox并使用其原生承诺:

 p = new Promise(function (resolve, reject) { throw 'err'; }); // Logs as error: Unhandled error: `err` 

简单地说 – firefox使用垃圾回收钩子来确定承诺处于未处理状态,并触发全局error handling程序,该处理程序默认在屏幕上写入。

现在,问题是本地承诺是不是很可用 – 因为在IE浏览器,他们不存在,并在Chrome未处理拒绝检测尚未实现 – 但它的到来,它会在那里。 同时,您可以使用像Bluebird这样的ES6兼容库,它将为您执行拒绝跟踪。

如果你想完成polyfill(我强烈build议不要) – torazaburo的polyfill有一些缺点。 它在promise原型上声明了一个可枚举的属性,通常这不是规范的devise方式 – 你需要inheritance promise来扩展它们,而不是猴子修补它们 – 遗憾的是目前没有任何实现支持这个。

所以简而言之:

  • 在使用它们之前,等待本机的承诺稳定下来 – 同时你可以使用像Bluebird这样的实现规范的库。 当它稳定没有,完全不会是一个问题。
  • 利用模式来检测错误 – 例如在这里查看处理器模式 。
  • 可用时使用开发工具,长堆栈跟踪和asynchronousdebugging是很大的优点。 另外请注意,如果您想要有意义的堆栈跟踪,则不应该抛出字符

祝你好运,快乐的编码。

不,AFAIK不是规范的一部分。 为了模仿它的行为,你应该在承诺链的范围之外的下一个勾号上抛出exception:

 p.catch(function(e) { setTimeout(function() { throw e; }); }); 

这基本上是图书馆如何实现的。 看Q文件摘录:

就像那样,但是…由此产生的拒绝原因在未来的事件循环中被作为例外抛出。

实现自己done

如果你想按照通常的理解来实现done的近似语义,那么就像:

 Promise.prototype.done = function(onFulfilled, onRejected) { this .then(onFulfilled, onRejected) .catch(function(e) { setTimeout(function() { throw e; }); }) ; }; 

设置error handling程序

如果你想自己处理这些错误,你可以设置一个error handling程序:

 Promise.onError = function(e) { console.log("The sky is falling", e); throw e; }; 

然后在下一个勾号上调用处理程序:

 Promise.prototype.done = function(onFulfilled, onRejected) { this .then(onFulfilled, onRejected) .catch(function(e) { setTimeout(Promise.onError || function() { throw e; }, 1, e); }) ; }; 

TC39的当前声明是,这个问题可以并且应该在浏览器引擎中用开发工具原生地解决。 这就是为什么他们在原生API中提供done的原因。

这确实是有争议的决定,请参阅以下关于这个问题的讨论链接:

https://github.com/domenic/promises-unwrapping/issues/19

http://mozilla.6506.n7.nabble.com/Where-d-Promise-done-go-td281461.html

https://github.com/promises-aplus/promises-spec/issues/43

https://github.com/slightlyoff/Promises/issues/33