Javascript ES6是否承诺支持';完成';应用程序编程接口?

Javascript ES6是否承诺支持';完成';应用程序编程接口?,javascript,promise,ecmascript-6,es6-promise,Javascript,Promise,Ecmascript 6,Es6 Promise,比如说 p = new Promise(function (resolve, reject) { throw 'err'; }); p.done(); 在大多数promise polyfill LIB中,done将抛出错误,当前执行将退出 但是如果我们使用p.then(),什么也不会发生。错误被承诺吞没了。如果使用p.catch,则无法退出当前执行。我想实现以下目标: try { // something } catch (err) { if (check(err))

比如说

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

p.done();
在大多数promise polyfill LIB中,done将抛出错误,当前执行将退出

但是如果我们使用
p.then()
,什么也不会发生。错误被承诺吞没了。如果使用
p.catch
,则无法退出当前执行。我想实现以下目标:

try {
    // something
} catch (err) {
    if (check(err)) {
        throw err;
    }
}
Promise.prototype.done = function(onFulfilled, onRejected) {
    this
        .then(onFulfilled, onRejected)
        .catch(function(e) {
            setTimeout(function() { throw e; });
        })
    ;
};

不,AFAIK
done
不是规范的一部分。要模拟其行为,您应该在下一个勾选中抛出异常,超出承诺链的权限:

p.catch(function(e) { 
    setTimeout(function() { throw e; });
});
这就是库实现
done
的基本方式。参见Q文件摘录:

很像当时的,但是。。。产生的拒绝原因在事件循环的未来回合中作为异常抛出

自己实施
done
如果您想要实现通常理解的
done
的近似语义,那么如下所示:

try {
    // something
} catch (err) {
    if (check(err)) {
        throw err;
    }
}
Promise.prototype.done = function(onFulfilled, onRejected) {
    this
        .then(onFulfilled, onRejected)
        .catch(function(e) {
            setTimeout(function() { throw e; });
        })
    ;
};
设置错误处理程序 如果您想自己处理这些错误,可以设置错误处理程序:

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

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

没有。 规范的未来版本不仅可能不支持
.done
,而且不需要它。引用Mariusz链接到的线程:

多梅尼克:

这仍然是容易出错的:如果你犯了一个错误,甚至一次都不遵守规则,你可能会永远沉默一个错误

马克·米勒(承诺概念的先驱):

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

RSVP的错误处理程序上的Yehuda Kats:

Promise.onError = function(e) {
    console.log("The sky is falling", e);
    throw e;
};
我们在RSVP中采用的方法是安装一个默认抛出的未处理承诺监视器

如果您知道将要附加异步错误处理程序,则可以通过附加noop失败处理程序来从该行为中选择特定的承诺。我们可能会有糖做这个(.undone:p)

根据我们的经验,将负担从每个人转移到可能希望附加异步错误处理程序的人身上是合适的

根据该规范之前的实际回购协议,多梅尼克说:

完成的工作将通过将未处理的拒绝跟踪功能集成到开发工具中来完成。据我和我自己所知,大多数TC39用户都认为这足以完成规范


规范委员会不仅忽略了
。完成了
,他们认为这是不必要的,而且容易出错。新的现代promise库自动检测未经处理的拒绝——这方面的两个例子是When promises和开创这一想法的Bluebird promises

.done
是一个工件-源于浏览器无法检测到未处理的拒绝。真相是——确定地检测它们是不可能的,但对于绝大多数情况来说,这是完全可能的

不相信我?打开Firefox,体验其本机承诺:

p = new Promise(function (resolve, reject) {
    throw 'err';
});
// Logs as error: Unhandled error: `err`
简单地说,firefox使用垃圾收集挂钩来确定承诺是在未处理状态下处理的,并触发一个全局错误处理程序,默认在屏幕上写入

现在,问题是本地承诺还不是很有用——因为在IE中它们不存在,在Chrome中未经处理的拒绝检测还没有实现——但它正在到来,而且它会出现。同时,您可以使用与ES6兼容的库,如Bluebird,它将为您进行拒绝跟踪

如果您想完成polyfill(我强烈建议您不要这样做),torazaburo的polyfill有一些缺点。它在promise原型上声明了一个可枚举属性,通常这不是规范的设计方式-您需要对promise进行子类化以扩展它们,而不是对它们进行修补-遗憾的是,目前没有任何实现支持这一点

简言之:

  • 在使用本机承诺之前,请等待它们稳定下来——与此同时,您可以使用实现规范的库,如Bluebird。当它稳定下来时,没有
    .done
    将根本不是问题
  • 利用模式来检测错误——例如,在这里查看
  • 如果可用,请使用开发人员工具,长堆栈跟踪和异步调试是一大优点。还请注意,如果希望有意义的堆栈跟踪,则不应抛出字符串

祝你好运,编码愉快。

这方面有什么帮助的,就是为什么推荐使用Promise库的原因。Bluebird可以很好地处理未捕获的异常,为您提供一堆导致当前事件的承诺。请参阅Bluebird Promise对象上的
longStackTraces
方法。@SecondRikudo native promises最终也可能会这样做-例如,他们已经在Firefox中这样做了。请注意,这个问题从2015年起就过时了,虽然我强烈不同意你的观点,但我真的很重视你在这些讨论中的奉献和参与。另外,谢谢你在这里发布它们,它们非常相关。关于上下文的好答案。