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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30540832/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 12:20:44  来源:igfitidea点击:

How to handle request-promise errors properly?

javascriptnode.jspromise

提问by RavenHursT

So I'm using request-promisein a script that I have that loops through a list of urls and fires of requests. Then I want to do something w/ the data received once all the requests are complete.

所以我在一个脚本中使用request-promise,我有一个循环遍历 url 和请求触发的列表。然后我想在所有请求完成后使用收到的数据做一些事情。

I have the following:

我有以下几点:

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);
});

As you can see.. http://httpstat.us/500throws a 500, which causes the .catch() block to be ran. I'm forcing an error. should.throw.error.to.console();should throw an error to the console, but instead, the script just exits silently w/o any error code (Process finished with exit code 0).

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

I'm assuming that request-promise is catching the error from node's httpwhen a page doesn't come back w/ 2xx code and then passing that back to the catch() callback. But any subsequent errors then end up failing silently. How in the world do I handle this so that the rest of my code will still throw errors properly?

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

Related GitHub issue

相关的 GitHub问题

采纳答案by RavenHursT

So apparently the .catch() in promises is basically a wrapper around a JS try-catch. So in order to have subsequent errors logged to the console after already having written one handler, you have to have a second handler to throw the eventual error to the console.

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

More info on GitHub here: https://github.com/request/request-promise/issues/48#issuecomment-107734372

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

回答by Gabriel L.

What do you mean by "any subsequent errors then end up failing silently"? If the original promise rpfails, the catchexecutes… at the time of failure.Once a promise is rejected, that's it, there can be no "subsequent errors."

“任何后续错误最终都会以静默方式失败”是什么意思?如果原始承诺rp失败,则失败时catch执行…… 一旦承诺被拒绝,就是这样,就不会有“后续错误”。

Also, shouldlooks like an assertion (e.g. from chai) which would suggest that you are trying to test this. Chai's should.throwdoesn't throw an error, it checks that an error has been thrown. If you are testing this, you need to indicate to the test (itblock) that the test is async, not sync —?usually by naming & invoking a doneparameter. Otherwise, the request will be sent out, and then before ANY response can be made, the script will synchronously end and no errors will be listened for.

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

What's more, you are spec'ing that something should throwto console, but nothing in your code throws! If you DID write in a throw, you should understand that throwinside a thenor catchwill simply cause the outgoing promise from that handler to be rejected with the thrown value (yes, catchexports a new promise, just like then— it is 100% sugar for .then(null, errHandler). If you want errors to be re-thrown back into the window, you need to finalize the chain with Bluebird's .done()promise method, accessed in request-promise via the somewhat arcane .promise().done(). But even in that case you'd still need to specify that you're doing an async test.

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

In short, it's not entirely clear what you think some of this code is supposed to be doing, and how it differs from your expectations. Please clarify!

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

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()`).