如何正确处理请求承诺错误?

时间:2015-05-30 00:09:26

标签: javascript node.js promise

所以我在一个脚本中使用request-promise,它循环遍历网址列表和请求的激活。然后,我希望在所有请求完成后接收数据。

我有以下内容:

var rp = require('request-promise');

rp.get({
    uri: 'http://httpstat.us/500',
    transform: function(body, res){
        res.data = JSON.parse(body);
        return res;
    }
}).then(function(res){
    results.push(res.data);
})
.catch(function(err){
    should.throw.error.to.console();
    var respErr  = JSON.parse(err.error);
    var errorResult = {
        origUrl: respErr.origUrl,
        error: respErr
    };
    results.push(errorResult);
});

正如您所看到的那样.. http://httpstat.us/500会抛出500,这会导致运行.catch()块。我在逼错。 should.throw.error.to.console();应该向控制台抛出错误,但是,脚本只是静默退出,没有任何错误代码(Process finished with exit code 0)。

我假设当一个页面没有返回w / 2xx代码然后将其传递回catch()回调时,请求承诺正在捕获节点http中的错误。但任何后续错误最终都会以无声的方式失败。我如何处理这个问题,以便我的其余代码仍能正确抛出错误?

相关GitHub issue

2 个答案:

答案 0 :(得分:1)

你是什么意思“任何后续错误然后最终失败”?如果原始承诺rp失败,则catch在失败时执行... 一旦承诺被拒绝,就是这样,就不会有“后续错误”。

此外,should看起来像是一个断言(例如来自chai),这表明您正在尝试对此进行测试。 Chai的should.throw不会抛出错误,它会检查是否抛出了错误。如果您正在对此进行测试,则需要向测试(it块)指示测试是异步的,而不是同步 - 通常是通过命名&调用done参数。否则,请求将被发送出去,然后在做出任何响应之前,脚本将同步结束并且不会收听任何错误。

更重要的是,你指的是throw要控制的东西,但代码throw中没有任何内容!如果您使用throw进行DID写入,则应该了解throwthen中的catch只会导致该处理程序的传出承诺被抛出的值拒绝(是的,catch导出一个新的承诺,就像then一样 - 它是.then(null, errHandler)的100%糖。如果你想将错误重新抛回窗口,你需要使用Bluebird的.done() promise方法完成链,通过有点神秘的.promise().done()在请求 - 承诺中访问。但即使在这种情况下,您仍然需要指定您正在进行异步测试。 / p>

简而言之,您认为某些代码应该在做什么以及它与您的期望有何不同并不完全清楚。请澄清!

var rp = require('request-promise');

rp.get({ // start an async call and return a promise
    uri: 'http://httpstat.us/500',
    transform: function(body, res){
        res.data = JSON.parse(body);
        return res;
    }
}).then(function(res){ // if rp.get resolves, push res.data
    results.push(res.data);
})
.catch(function(err){ // if rp.get rejects (e.g. 500), do this:
    should.throw.error.to.console(); // test if something is thrown (but nothing has been!)
    var respErr  = JSON.parse(err.error);
    var errorResult = {
        origUrl: respErr.origUrl,
        error: respErr
    };
    results.push(errorResult); // push an object with some of the error info into results
});

// this line (e.g., end of script) is reached before any of the async stuff above settles. If you are testing something, you need to make the test async and specify when it's complete by invoking `done()` (not the same as ending the promise chain in Bluebird's `.done()`).

答案 1 :(得分:0)

显然,promises中的.catch()基本上是JS try-catch的包装器。因此,为了在已经编写了一个处理程序后将后续错误记录到控制台,您必须有第二个处理程序将最终错误抛给控制台。

有关GitHub的更多信息:https://github.com/request/request-promise/issues/48#issuecomment-107734372