【问题标题】:Node giving UnhandledPromiseRejection warning, when I'm *sure* I'm catching the rejection节点发出 UnhandledPromiseRejection 警告,当我*确定*收到拒绝时
【发布时间】:2017-12-21 19:45:14
【问题描述】:

我正在使用 node-libcurl。我有一个小模块,其中有一个 curl 请求队列。下面是实际发出 curl 请求的函数的样子:

const Curl = require('node-libcurl').Curl;

let timeoutCount = 0;
function _getOData(url) {
    const curl = new Curl();
    return new Promise((resolve, reject) => {
        curl.setOpt(Curl.option.URL, url);
        curl.setOpt(Curl.option.HTTPAUTH, Curl.auth.NTLM);
        curl.setOpt(Curl.option.SSL_VERIFYPEER, false);
        curl.setOpt(Curl.option.SSL_VERIFYHOST, false);
        curl.setOpt(Curl.option.POST, 0);
        curl.setOpt(Curl.option.HTTPHEADER, ['Accept: application/json']);

        let done = false;

        curl.on('end', function (statusCode, body, headers) {
            done = true;
            const retObj = JSON.parse(body);
            resolve(retObj);
            curl.close();
        });

        curl.on('error', function (e) {
            done = true;
            reject(e);
            curl.close();
        });

        curl.perform();

        setTimeout(() => {
            if (!done) {
                timeoutCount++;
                reject(new Error(`request timed out: ${timeoutCount}`));
            }
        },1000*10);
    })
}

我在控制台中不断收到此错误:(node:26616) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 6): Error: request timed out -- 所以我添加了 timeoutCount,因为我确信我捕获了所有 Promise 错误,尽管收到了此警告。

对 _getOData 函数的每次调用都发生在队列逻辑中,具体来说,这段代码是调用 _getOData 的唯一代码:

        const p = _getOData(nextObj.url);
        p.then(nextObj.cb);
        p.catch((e) => {
            if (e.message.includes("request timed out")) {
                queue.add(nextObj.url, nextObj.cb, nextObj.ecb);
                return true;
            } else {
                nextObj.ecb(e);
                return false;
            }
        });

所以我在e.message.includes("request timed out") 之后设置了一个断点,并且每次发生请求超时错误时它都会打到那里,所以我确信没有“未处理的承诺拒绝”。每一个承诺拒绝都会经历这个问题。当变量在那里中断时,我会检查该变量,以确保 timeoutCount 存在,并且始终存在,然后它仍然始终作为未处理的承诺拒绝记录到控制台。

这是怎么回事?

【问题讨论】:

  • 你没有发现p.then(nextObj.cb);这里可能的拒绝 - .then返回的承诺没有发现
  • @JaromandaX 当然,重要的是我得到了来自p 的承诺,无论我在哪里在哪里得到它。它不是在 p.then() 中被捕获的,而是在之后被捕获的。
  • 哦,我想我误读了你起初所说的@JaromandaX,但我确信 .then 返回的承诺没有错误。我知道它所说的错误是未处理的错误是我的p.catch 内部的错误,因为它控制台记录了错误消息并且我已经验证了它是那个错误。
  • @JaromandaX 你是对的,.then 返回的新承诺也需要它自己的.catch,这就是导致该消息的原因。谢谢你。我是从一个系统进入这个系统的但显然这是不同的,这是有道理的

标签: javascript node.js promise


【解决方案1】:

您可能在队列中而不是在堆栈中捕获拒绝。您会使用以下代码收到该错误(警告):

var p = Promise.reject("hello world");//do not catch on the stack
setTimeout(
  x=>p.catch(err=>console.log("catching:",err))//caught error on queue
  ,100
);

如果您要在队列中捕获拒绝,那么您可以执行以下操作:

saveReject = p =>{
  p.catch(ignore=>ignore);
  return p;//catch p but return p without catch
}
var p = saveReject(Promise.reject("hello world"));//creating promise on the stack
setTimeout(
  x=>p.catch(err=>console.log("catching:",err))//caught error on queue
  ,100
);

关于队列和堆栈的信息可以在here找到。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-01
    • 2021-11-17
    相关资源
    最近更新 更多