Dojo - 吞下promise的ReferenceError异常

cas*_*son 5 dojo exception promise deferred

在jQuery中,如果你在ajax回调方法中出错,你将得到一个正确的控制台错误信息和stacktrace.

$.get("https://api.github.com/users/octocat/orgs", function() {
  var a = FAIL;
});
Run Code Online (Sandbox Code Playgroud)

然而,在使用道场/请求/ XHR道场似乎这些愚蠢的错误被完全吞噬.我运行它时控制台中唯一的东西是"然后"和"总是".

require(["dojo/request/xhr" ], function(xhr) {
    var promise = xhr.get("https://api.github.com/users/octocat/orgs");
    promise.then(function(data) {
        console.log('then');
        var a = FAIL;
        console.log('goodbye');
    }, function() {
        console.log('error');
    });
    promise.otherwise(function() {
        console.log('otherwise');
    });
    promise.always(function() {
        console.log('always');
    });
});
Run Code Online (Sandbox Code Playgroud)

使用已弃用的dojo.xhrGet,问题略有改善.我收到一个控制台错误消息,我的错误处理程序被调用,但它只是说"ReferenceError {}"并为我提供了一个永远不会指向我拥有的函数的堆栈跟踪:

dojo.xhrGet({
    url: "https://api.github.com/users/octocat/orgs",
    load: function() {
        console.log('dojo.xhrGet.load');
        var a = FAIL;

        console.log('goodbye dojo.xhrGet.load');
    },
    error: function() {
        console.log('dojo.xhrGet.error');
    },
    handle: function() {
        console.log('dojo.xhrGet.handle');
    }
});
Run Code Online (Sandbox Code Playgroud)

当编写一个程序,我们会犯错误,这是不错的,我们有一个像Chrome开发者工具的工具给我们指出这些错误.当您可以看到堆栈跟踪和错误消息时,找到错误所需的时间显然比没有反馈时快得多.我得到了道场没有反馈,我不能相信这样的通俗图书馆可以以这种方式操作.我究竟做错了什么?

Dav*_*lin 4

您对从 jQuery 继承的 Promise 的理解与其他人的理解根本不同(检查 Promises/a+ 实现)。对于这个答案的其余部分,我将讨论 Promise/a+ 兼容的 Promise。Dojo 的 Deferred 实际上并不符合 a+ 标准,但它足够接近,我在这里讨论的所有内容都同样适用。

Promise 是不可变的,您无法通过调用来更改 Promise 状态then。Promise 代表最终的值,通过说“一旦值准备好,执行此操作”来更改 Promise 是毫无意义的。

那么,希望这能解释为什么你的错误处理程序没有被调用,但是捕获错误的基本思想仍然是完全可能的。您只需要使用返回值。当您调用thenPromise 时,它​​会返回一个新的且(几乎总是)不同的 Promise。这个新的 Promise 非常特殊,如果原始 Promise 被解析,并且您传递的成功处理程序被调用,并且返回一些东西,那么该东西将是第二个 Promise 的解析值。

同样,如果错误处理程序(在第一个 Promise 上)被触发,并且该函数返回某些内容,则该内容将成为第二个 Promise 的解析值。对于抛出的错误也是如此,它们被传递给错误处理程序(第二个承诺的!)。

这是您以 more Promise/a+ 方式编写的第一个代码示例:

require(["dojo/request/xhr" ], function(xhr) {
    var promise = xhr.get("https://api.github.com/users/octocat/orgs");
    promise.then(function(data) {
        console.log('then');
        var a = FAIL;
        console.log('goodbye');
    }, function() {
        console.log('error');
    }).then(null, function() {
        console.log('otherwise');
    });

    promise.always(function() {
        console.log('always');
    });
});
Run Code Online (Sandbox Code Playgroud)

我不太明白你想用always 函数做什么,所以我不知道该把它放在哪里。关于调用堆栈的主题,我建议查看 Q Promise 库,它具有非常先进的异步调用堆栈支持。