承诺解析器/拒绝器会触发它的反面吗?

时间:2015-10-31 02:10:45

标签: javascript promise es6-promise

如果我们有以下承诺,其评论中的问题答案是什么?

p.then(function ok () {
    // Can we get err() to trigger from inside here?
}, function err () {
    // Can we get ok() to trigger from inside here?
});

我知道可以附加新then可以等待结果或反转p的结果,但我想知道,假设p是常数,是否条件也可以递归地相互调用(并且不将函数分配给变量并按名称调用它们)......

更新

我的用例如下。

在IndexedDB中,打开数据库时,您可以监听以下内容:

db.onsuccess = ...
db.onerror = ...
db.onblocked = ...

db.js,我正在扩展以满足我的需求的库,使用Promise API添加这些事件,以便成功解决承诺,错误或阻止将拒绝承诺。

监听阻塞的一个常见用例是关闭导致阻塞的数据库连接,然后IndexedDB会自动调用onsuccess。问题是,如果我们将onblocked视为拒绝,则显然无法重新触发解决条件(即onsuccess)。为了解决这个问题,我可以将阻塞作为回调提供,但是我想知道是否有任何方法可以使用Promises方法专门执行它,因为从技术上讲,错误将不再是错误,并且希望通过处理成功,让原始决心回调的机会恢复。

2 个答案:

答案 0 :(得分:2)

因为你将错误处理程序指定为.then的第二个参数,它在语义上意味着只有在承诺" p"被拒绝了。所以这两条路是相互排斥的。这也意味着,如果在你的'" ok"处理程序你抛出一个错误,它不会被" err"功能

相比之下,如果您的代码使用了.catch,那么它会在成功处理程序中捕获来自承诺拒绝,的错误。所以如果你有这个:

p.then(function () {
    throw new Error("Within the .then");
}).catch(function (error) {
    console.log(error);
});

无论p是已解决还是拒绝,它总是会将错误记录到控制台。

所以对于你的第一个问题:ok处理程序可以触发err函数,IF而不是用你做的两个参数做.then(successHandler).catch(errorHandler)。但是对于第二个问题,它没有"没有"无论如何 - 错误处理程序或" catch"都没有逻辑路径。到由于拒绝而明确跳过的路径。

根据更新的问题说明进行更新

假设你在" catch"中得到某种指标。关于错误发生的原因(以及你是否真的应该拒绝,或者你是否应该继续,好像它是否成功),你没有理由不能像成功一样调用同样的功能。只是它有两个入口点:

p.then(successHandler, failureHandler)
 .then( /* other stuff if you want to chain */ )
 .catch(function(e) {
    // catch-all handler just in case
 })

function successHandler(data) {
    // Do something. Note that to avoid 
    // "breaking the promise chain", the code here
    // should either be all-synchronous or return another promise.
}

function failureHandler(error) {
    if (error.wasDueToBlocking()) {
        return successHandler(error.partialData);
    } else {
        // handle the true error. Again, to avoid 
        // "breaking the promise chain", the code here
        // should either be all-synchronous or return another promise.
    }
}

根据不创建独立命名函数/变量的要求更新2

我不完全确定你为什么不想要命名的功能,而我即将展示的方法可能有点奇怪。但可以想象,你可以做到这一点,相反,成功处理程序除了链接到一个实际的公共处理程序之外什么都不做。

p.then(function(data) {
    return {goOn: true, data: data};
 }, function(error) {
    if (error.wasDueToBlocking()) {
        return {goOn: true, data: error.partialData};
    } else {
        // Do some errorHandling logic
        return {goOn: false};
    }
 }
 .then(function(passedThroughData) {
    if (passedThroughData.goOn) {
        // Do something with it.
        // Otherwise ignore, since error handler
        // already took care of whatever it needed above
    }
 })
 .then(function() {
    // whatever you wanted to happen next
 })
 .catch(function(e) {
    // catch-all handler just in case
 })

答案 1 :(得分:2)

  

我们可以从err()触发ok吗?   我们可以从ok()触发err吗?

没有。 promises spec强制要求两个then处理程序中的一个最多被调用。如果承诺履行了第一次被调用,如果承诺拒绝第二次意愿,承诺不能同时做这两件事。

因此,虽然您可以轻松地创建两个命名函数并手动调用,但在编程方式上不能触发承诺调用另一个函数。

  

我的用例如下[...]

您实际上正在寻找的是

db.open().catch(function(err) {
    if (err.isBlocking)
        return db.closeAndWaitForNextSuccess(err.blocker); // get another promise
    else
        throw err;
}).then(function ok(res) {
    …
});