简体   繁体   English

Javascript ES6会答应支持'完成'api吗?

[英]Will Javascript ES6 promise support 'done' api?

For example 例如

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

p.done();

In most promise polyfill libs, the done will throw an error, and the current execution will exit. 在大多数promise polyfill库中,done将抛出一个错误,当前执行将退出。

But if we use p.then() , nothing will happen. 但是如果我们使用p.then() ,什么都不会发生。 The error is swallowed by the promise. 承诺吞噬了这个错误。 If we use p.catch , we have no way to exit current execution. 如果我们使用p.catch ,我们无法退出当前执行。 I want to achieve something like: 我希望实现以下目标:

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

No. 没有。

Not only will .done likely not be supported in the future versions of the spec - it is unneeded. 不仅将.done可能不会在规范的未来版本的支持-这是不需要的。 Quoting from the threads Mariusz linked to: 引用Mariusz与之相关的主题:

Domenic: Domenic:

it's still error-prone: if you slip up and don't follow the rule even once, you might silence an error forever. 它仍然容易出错:如果你滑倒并且不遵守规则,你可能会永远沉默错误。

Mark Miller (who pioneered the concept of promises): 马克·米勒(谁开创了承诺的概念):

Note that weak-refs, hopefully in ES7, will provide us one of the diagnostic tools we need to bridge this gap. 请注意,希望ES7中的弱参考将为我们提供弥补这一差距所需的诊断工具之一。 Using weak-refs, if a rejected promise gets collected without having notified any handlers, we can arrange that this generates a diagnostic. 使用弱引用,如果在未通知任何处理程序的情况下收集被拒绝的承诺,我们可以安排这会产生诊断。 The promise implementation would have to keep the reason in the promise's executor (post-mortem gc handler), so that it has the diagnostic to report after discovery that the promise has been rejected. promise实现必须将原因保留在promise的执行者(post-mortem gc handler)中,以便在发现promise被拒绝后具有诊断报告。

Yehuda Kats on RSVP's error handler: 在RSVP的错误处理程序上的Yehuda Kats:

The approach we're taking in RSVP is to install an unhandled promise monitor that throws by default. 我们在RSVP中采用的方法是安装默认情况下抛出的未处理的promise监视器。

You can opt a particular promise out of this behavior by attaching a noop failure handler, if you know that you will be attaching asynchronous error handlers. 如果您知道将附加异步错误处理程序,则可以通过附加noop失败处理程序来选择特定的承诺。 We will probably have sugar for this (.undone :p) 我们可能会为此加糖(.undone:p)

In our experience, moving the burden from literally everyone to people who may want to attach async error handlers is appropriate. 根据我们的经验,将负担从字面上的每个人转移到可能想要附加异步错误处理程序的人是合适的。

And, from the actual repo that preceded the spec, Domenic said: 并且,根据规范之前的实际回购,Domenic说:

done's job will be done by integrating unhandled rejection tracking functionality into dev tools. 完成的工作将通过将未处理的拒绝跟踪功能集成到开发工具中来完成。 Most TC39ers, from what I understand, as well as myself, perceive that as enough for the spec to be complete. 根据我的理解,以及我自己,大多数TC39都认为足以使规范完整。


The spec committee did not just ignore .done , they deemed it was unnecessary and error prone. 规范委员会不仅忽视了.done ,他们认为这是不必要的,容易出错。 New modern promise libraries automatically detect unhandled rejections - two examples of this are When promises and Bluebird promises that pioneered the idea. 新的现代承诺库自动检测未处理的拒绝 - 两个例子是当Promises和Bluebird承诺开创这个想法。

.done is an artifact - originating from the fact the browser could not detect unhandled rejections. .done是一个工件 - 源于浏览器无法检测到未处理的拒绝这一事实。 Truth is - detecting them deterministically is impossible but for the vast majority of cases it is completely possible. 事实是 - 确定性地检测它们是不可能的,但对于绝大多数情况来说,它是完全可能的。

Don't believe me? 不相信我? Open Firefox and play with its native promises: 打开Firefox并使用其原生承诺:

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

Simply put - firefox uses garbage collection hooks in order to determine promises were disposed in an unhandled state and fires a global error handler which defaults to writing on the screen. 简单地说 - firefox使用垃圾收集钩子来确定promises处于未处理状态并触发一个全局错误处理程序,默认情况下在屏幕上写入。

Now, the problem is native promises are not very usable yet - since in IE they don't exist and in Chrome unhandled rejection detection was not yet implemented - but it's coming and it'll be there. 现在,问题是本机承诺还不是很有用 - 因为在IE中它们不存在而且在Chrome中未处理的拒绝检测尚未实现 - 但它即将到来并且它将会存在。 Meanwhile you can use an ES6 compatible library like Bluebird which will do this rejection tracking for you. 同时你可以使用像Bluebird这样的ES6兼容库,它会为你做这种拒绝跟踪。

If you want to polyfill done (which I strongly recommend against) - the polyfill by torazaburo has a few shortcomings. 如果你想完成polyfill(我强烈建议反对) - torazaburo的polyfill有一些缺点。 It declares an enumerable property on the promise prototype and generally this is not how the spec was designed - you are expected to subclass promises in order to extend them rather than monkey patch them - sadly no implementations currently support this. 它在promise原型上声明了一个可枚举的属性,通常这不是规范的设计方式 - 你需要将promises 子类化为扩展它们而不是猴子修补它们 - 遗憾的是没有实现当前支持这个。

So in short: 简而言之:

  • Wait for native promises to stabilize before you use them - in the meanwhile you can use libraries that implement the spec like Bluebird. 在使用它们之前等待本机承诺稳定 - 同时您可以使用实现规范的库,如Bluebird。 When it stabilizes not having .done will not be an issue at all. 当它稳定没有.done根本不会成为问题。
  • Utilize patterns for detecting errors - for example check out the disposer pattern here. 利用模式检测错误 - 例如, 这里查看处理器模式
  • Use the developer tools when available, long stack traces and and async debugging are big plusses. 在可用时使用开发人员工具,长堆栈跟踪和异步调试是很重要的。 Also note you should not throw strings if you want meaningful stack traces. 另请注意,如果需要有意义的堆栈跟踪,则不应抛出字符串。

Good luck and happy coding. 祝你好运,编码愉快。

No, AFAIK done is not part of the spec. 不,AFAIK done的不是规范的一部分。 To mimic its behavior, you should throw the exception on the next tick, outside the purview of the promises chain: 为了模仿它的行为,你应该在promises链的范围之外的下一个tick上抛出异常:

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

This is essentially how libraries implement done . 这实质上是库工具怎么done See excerpt from Q documents: 参见Q文件的摘录:

Much like then , but ... the resulting rejection reason is thrown as an exception in a future turn of the event loop . 就像then一样,但是...... 在事件循环的未来转向中,所产生的拒绝原因被抛出作为例外。

Implementing done yourself 自己done实施

If you want to implement the approximate semantics of done as typically understood, then something like: 如果你想实现通常理解的done的近似语义,那么类似于:

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

Setting up an error handler 设置错误处理程序

If you want a chance to handle these errors yourself, you could set up an error handler: 如果您希望自己有机会处理这些错误,可以设置错误处理程序:

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

Then invoke the handler on the next tick: 然后在下一个tick上调用处理程序:

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

Current statement of TC39 is that this issue can be and should be solved natively in browser engines with developer tools. TC39的当前声明是,这个问题可以并且应该在使用开发人员工具的浏览器引擎中本地解决。 That's why they're opposite providing done within native API. 这就是为什么他们在本机API中提供done的原因。

It's indeed controversial decision, see following links for discussions on that matter: 这确实是一个有争议的决定,请参阅以下关于此事的讨论链接:

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

http://mozilla.6506.n7.nabble.com/Where-d-Promise-done-go-td281461.html 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/promises-aplus/promises-spec/issues/43

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM