当前位置: 首页 > 面试题库 >

JavaScript连锁承诺不会被拒绝

盖晋
2023-03-14
问题内容

我在理解为什么拒绝不通过承诺链传递时遇到问题,我希望有人能够帮助我理解原因。对我来说,将功能附加到承诺链上意味着我有意要实现的原始承诺。很难解释,所以让我先显示我的问题的代码示例。(注意:此示例使用的是Node和延迟的节点模块。我使用Dojo
1.8.3对此进行了测试,并得到了相同的结果)

var d = require("deferred");

var d1 = d();

var promise1 = d1.promise.then(
    function(wins) { console.log('promise1 resolved'); return wins;},
    function(err) { console.log('promise1 rejected'); return err;});
var promise2 = promise1.then(
    function(wins) { console.log('promise2 resolved'); return wins;},
    function(err) { console.log('promise2 rejected'); return err;});
var promise3 = promise2.then(
    function(wins) { console.log('promise3 resolved'); return wins;},
    function(err) { console.log('promise3 rejected'); return err;});
d1.reject(new Error());

运行此操作的结果是以下输出:

promise1 rejected
promise2 resolved
promise3 resolved

好吧,对我来说,这个结果没有意义。通过附加到这个承诺链,每个人都暗示着它的意图将取决于d1的成功解析以及将结果传给链下的情况。如果promise1中的promise没有收到wins值,而是在其错误处理程序中获得了一个err值,那么链中的下一个promise如何调用其成功函数?它无法将有意义的价值传递给下一个承诺,因为它本身没有获得价值。

我可以用另一种方式描述我的想法:约翰,金杰和鲍勃三个人。约翰拥有一家小店。生姜进入他的商店,要求一袋各种颜色的小部件。他没有库存,因此他向经销商发送要求将其装运给他。同时,他给姜生了雨水支票,说他欠了她一袋小物件。鲍勃发现姜正在得到这些小部件,并要求他在完成处理后得到蓝色小部件。她同意并给他一张便条,说明她会的。现在,John的分销商找不到供应商提供的任何小部件,而制造商也不再制造它们,因此,他们通知John,后者又通知Ginger她无法获得这些小部件。鲍勃在没有自己的情况下如何从金杰那里得到一个蓝色小部件?

我对这个问题的第三个更现实的看法是。假设我有两个要更新到数据库的值。一个依赖于另一个的ID,但是直到将其插入数据库并获得结果后,我才能获取ID。最重要的是,第一个插入依赖于来自数据库的查询。数据库调用返回承诺,用于将两个调用链接成一个序列。

var promise = db.query({parent_id: value});
promise.then(function(query_result) {
    var first_value = {
        parent_id: query_result[0].parent_id
    }
    var promise = db.put(first_value);
    promise.then(function(first_value_result) {
        var second_value = {
            reference_to_first_value_id: first_value_result.id
        }
        var promise = db.put(second_value);
        promise.then(function(second_value_result) {
            values_successfully_entered();
        }, function(err) { return err });
    }, function(err) { return err });
}, function(err) { return err });

现在,在这种情况下,如果db.query失败,它将调用第一个的err函数。但随后它将调用下一个承诺的成功功能。虽然该承诺期望第一个值的结果,但它会从其错误处理程序函数中获取错误消息。

所以,我的问题是,如果我必须测试成功函数中的错误,为什么会有错误处理功能?

很抱歉,这个长度。我只是不知道该怎么解释。

更新和更正

(请注意:我删除了我曾经对某些评论做出的回复。因此,如果有人对我的回复发表了评论,那么我删除该评论后,他们的评论可能似乎已经脱离上下文了。很抱歉,我正在尝试将其尽可能简短)

谢谢大家回答。首先,我要向所有人道歉,因为我写得这么差,尤其是我的伪代码。我有点太激进了,试图使它简短。

多亏了Bergi的回应,我认为我发现了自己的逻辑错误。我想我可能忽略了另一个导致我遇到的问题。这可能导致承诺链的工作方式与我预期的不同。我仍在测试代码的不同元素,因此我什至无法提出一个适当的问题来查看我做错了什么。我确实想更新大家,并感谢您的帮助。


问题答案:

对我来说,这个结果没有意义。通过附加到此诺言链,每个人都暗示着它的意图是,它取决于d1的成功解析以及结果沿链向下传递

否。您所描述的不是链,而是将所有回调附加到d1。但是,如果要与链接then,则for的结果promise2取决于的分辨率promise1
以及then回调如何对其进行处理

文档状态:

为回调结果返回一个新的promise。

.then通常根据Promises /
A规范
(或更严格的Promsises / A +
1)来查看该方法。这意味着回调外壳程序返回的promise将被同化为的解决方案promise2,并且如果没有成功/错误处理程序,则相应的结果将被直接传递给promise2-因此,您可以简单地
省略处理程序 以传播错误。

但是,如果 处理 了错误,则结果promise2将被视为固定的并且将使用该值来实现。如果您不希望这样做,则必须
重新throw输入错误,就像在try-catch子句中一样。另外,您可以从处理程序中返回(待)拒绝的承诺。不知道Dojo拒绝的方式是什么,但是:

var d1 = d();

var promise1 = d1.promise.then(
    function(wins) { console.log('promise1 resolved'); return wins;},
    function(err) { console.log('promise1 rejected'); throw err;});
var promise2 = promise1.then(
    function(wins) { console.log('promise2 resolved'); return wins;},
    function(err) { console.log('promise2 rejected'); throw err;});
var promise3 = promise2.then(
    function(wins) { console.log('promise3 resolved'); return wins;},
    function(err) { console.log('promise3 rejected'); throw err;});
d1.reject(new Error());

鲍勃在没有自己的情况下如何从金杰那里得到一个蓝色小部件?

他不应该。如果没有错误处理程序,他将仅感知到消息((来自John的(来自发行商)John的)来自Ginger的消息),没有剩余的小部件。但是,如果Ginger为这种情况设置了一个错误处理程序,那么如果John或其分销商没有蓝色的东西,她仍然可以通过给鲍勃一个绿色的小部件实现自己的诺言,即给鲍勃一个小部件。

要将错误回调转换为metapher,return err从处理程序中就像是说“如果没有小部件,请给他注意没有小部件-它与所需的小部件一样好”。

在数据库情况下,如果db.query失败,它将调用第一个的err函数,然后

……这意味着错误在那里得到处理。如果不这样做,则忽略错误回调。顺便说一句,您的成功回调没有return建立它们的承诺,因此它们似乎毫无用处。正确的是:

var promise = db.query({parent_id: value});
promise.then(function(query_result) {
    var first_value = {
        parent_id: query_result[0].parent_id
    }
    var promise = db.put(first_value);
    return promise.then(function(first_value_result) {
        var second_value = {
            reference_to_first_value_id: first_value_result.id
        }
        var promise = db.put(second_value);
        return promise.then(function(second_value_result) {
            return values_successfully_entered();
        });
    });
});

或者,由于您不需要闭包来访问先前回调的结果值,甚至:

db.query({parent_id: value}).then(function(query_result) {
    return db.put({
        parent_id: query_result[0].parent_id
    });
}).then(function(first_value_result) {
    return db.put({
        reference_to_first_value_id: first_value_result.id
    });
}.then(values_successfully_entered);


 类似资料:
  • 问题内容: 我在理解为什么拒绝不通过承诺链传递时遇到问题,我希望有人能够帮助我理解原因。对我而言,将功能附加到承诺链上意味着我有意要实现的原始承诺。很难解释,所以让我先显示我的问题的代码示例。(注意:此示例使用的是Node和延迟的节点模块。我使用Dojo 1.8.3对此进行了测试,并得到了相同的结果) 运行此操作的结果是以下输出: 好吧,对我来说,这个结果没有道理。通过附加到该承诺链,每个人都暗示

  • 问题内容: 我已经阅读了几篇有关该主题的文章,但是我仍然不清楚是否与抛出错误之间有区别。例如, 使用Promise.reject 使用抛出 我倾向于仅使用它,因为它更短,但我想知道一个相对于另一个是否有任何优势。 问题答案: 使用一个相对于另一个没有优势,但是,在特定情况下无法使用。但是,这些情况可以解决。 每当您进入promise回调时,都可以使用。但是,如果您在任何其他异步回调中,则必须使用。

  • 问题内容: 我想做一些非常简单的事情,但是我一点都不懂… 我希望依次对funcs数组的每个元素进行“处理”,然后输出如下所示: 我无法做到这一点:(应该很简单,我什么都没发现:( 问题答案: 从您的示例来看,我认为您已经看到了Q自述文件中的Sequences部分,但未能理解它。 当每个函数的输出作为输入传递给下一个函数时,原始示例使用“瀑布”模型: 但是您只想按顺序执行我们所有的函数,因此您只需将

  • 问题内容: 我正在尝试用正确的方法表示正确的方法,以指示内发生故障。 如果诺言没有失败,(即返回诺言的操作是否正常工作,例如返回状态200的AJAX请求),但是我认为结果无效,通常我会这样做弹出窗口,向用户说明问题,然后执行“返回假”;尽早退出该方法。 但是,有了承诺,如果我想从.then()内部做类似的事情,我就被引导去相信我应该做的是抛出一个错误,而应该让它被.catch()抓住。 ),我已经

  • 问题内容: 我从控制器内部的异步服务获取数据,如下所示: 我的问题: 当我从服务中获得错误而又不返回承诺时,如何再次查询服务。 在我的服务中这样做会更好吗? 谢谢! 问题答案: 您可以在服务本身而不是控制器中重试该请求。 因此,可能是这样的: 您可以摆脱控制器中的错误功能:

  • 问题内容: 我需要创建链式承诺: 如果我将errorCallback放在第一个中,则第二个将被解析,并调用其successCallback。但是,如果我删除了,那么第二个承诺将被拒绝。 根据Angular JS的文档,传播拒绝的唯一方法是返回并且它看起来并不明显,尤其是因为即使不需要它,我也必须注入服务。 也可以通过在中引发异常来完成此操作,但是它将异常跟踪写入控制台,这不好。 还有另一种选择可以