Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/443.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 被束缚的承诺不会被拒绝_Javascript_Node.js_Dojo_Promise_Deferred - Fatal编程技术网

Javascript 被束缚的承诺不会被拒绝

Javascript 被束缚的承诺不会被拒绝,javascript,node.js,dojo,promise,deferred,Javascript,Node.js,Dojo,Promise,Deferred,我很难理解为什么拒绝不会通过承诺链传递,我希望有人能帮助我理解为什么。对我来说,将功能附加到承诺链意味着我依赖于原始承诺来实现的意图。这很难解释,所以让我先展示一个问题的代码示例。(注意:本例使用的是Node和deferred Node模块。我用Dojo 1.8.3进行了测试,得到了相同的结果) 运行此操作的结果是以下输出: promise1 rejected promise2 resolved promise3 resolved 好吧,对我来说,这个结果没有意义。通过附加到该承诺链,每个承诺

我很难理解为什么拒绝不会通过承诺链传递,我希望有人能帮助我理解为什么。对我来说,将功能附加到承诺链意味着我依赖于原始承诺来实现的意图。这很难解释,所以让我先展示一个问题的代码示例。(注意:本例使用的是Node和deferred Node模块。我用Dojo 1.8.3进行了测试,得到了相同的结果)

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

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

我可以用另一种方式来描述我的想法:有三个人,约翰、金吉尔和鲍勃。约翰拥有一家小工具店。金吉尔走进他的商店,要了一袋各色的小玩意儿。他没有存货,所以他向分销商发出请求,要求将货物运给他。与此同时,他给了金吉尔一张改天支票,说他欠她一袋小玩意儿。Bob发现Ginger正在获取这些小部件,并要求他在Ginger处理完这些小部件后获取蓝色小部件。她同意了,并给了他一张便条,说明她会的。现在,John的经销商在他们的供应中找不到任何小部件,制造商也不再生产,所以他们通知John,而John又通知Ginger她无法获得这些小部件。Bob怎么能从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
,那么
promise2
的结果取决于
promise1
的分辨率以及
then
回调如何处理它

文件规定:

返回回调结果的新承诺

.then
方法通常是根据(或更严格的)标准来看待的。这意味着回调外壳返回承诺将被同化为
promise2
的解析,如果没有成功/错误处理程序,相应的结果将直接传递给
promise2
——因此您可以简单地忽略处理程序来传播错误

但是,如果处理了错误,则生成的
promise2
被视为是固定的,并将使用该值来实现。如果您不想这样做,您必须重新抛出错误,就像在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());
Bob怎么能从Ginger那里得到一个蓝色的小部件,而她自己却没有

他不应该这样做。如果没有错误处理程序,他只会感知到来自Ginger的消息((来自分发服务器)来自John)没有小部件了。然而,如果Ginger为这种情况设置了一个错误处理程序,她仍然可以兑现她的承诺,如果John或他的经销商没有留下蓝色的,她可以从自己的小屋给Bob一个绿色的小部件

要将错误回调转换为metapher,处理程序返回的
return err
就像说“如果没有剩下小部件,只需告诉他没有剩下小部件-它与所需的小部件一样好”

在数据库情况下,如果
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());
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);
promise1 rejected
promise2 rejected
promise3 rejected
promise.then(function(first_value) {
    console.log('promise1 resolved');
    var promise = db.put(first_value);
    promise.then(function (second_value) {
         console.log('promise2 resolved');
         var promise = db.put(second_value);
         promise.then(
             function (wins) { console.log('promise3 resolved'); },
             function (err) { console.log('promise3 rejected'); return err; });
    }, function (err) { console.log('promise2 rejected'); return err;});
}, function (err) { console.log('promise1 rejected'); return err});
promise1 rejected
function (err) { console.log('promise1 rejected'); throw err; });
class TraceError extends Error {
  constructor(message, ...causes) {
    super(message);

    const stack = Object.getOwnPropertyDescriptor(this, 'stack');

    Object.defineProperty(this, 'stack', {
      get: () => {
        const stacktrace = stack.get.call(this);
        let causeStacktrace = '';

        for (const cause of causes) {
          if (cause.sourceStack) { // trigger lookup
            causeStacktrace += `\n${cause.sourceStack}`;
          } else if (cause instanceof Error) {
            causeStacktrace += `\n${cause.stack}`;
          } else {
            try {
              const json = JSON.stringify(cause, null, 2);
              causeStacktrace += `\n${json.split('\n').join('\n    ')}`;
            } catch (e) {
              causeStacktrace += `\n${cause}`;
              // ignore
            }
          }
        }

        causeStacktrace = causeStacktrace.split('\n').join('\n    ');

        return stacktrace + causeStacktrace;
      }
    });

    // access first error
    Object.defineProperty(this, 'cause', {value: () => causes[0], enumerable: false, writable: false});

    // untested; access cause stack with error.causes()
    Object.defineProperty(this, 'causes', {value: () => causes, enumerable: false, writable: false});
  }
}
throw new TraceError('Could not set status', srcError, ...otherErrors);
TraceError#cause - first error
TraceError#causes - list of chained errors