【问题标题】:Request Promise unhandled reject请求 Promise 未处理的拒绝
【发布时间】:2019-12-16 23:17:57
【问题描述】:

基本上,在我收到此 POST 的返回并将此信息保存在数据库中之后,我必须执行一个 POST 请求并尝试将此数据保存在 API 上。

所以,我在另一个 Promise 中调用了 Promise (saveProcessedData or saveErrorData),按预期工作,但发出警告:

未处理的拒绝状态代码错误:400

const sendData = async(data, item) => {

    let payload = [],
        dataProcessed = [];

    let options = { 
        method: data.endpoint.method,
        url: api._url + data.endpoint.url,
        headers: 
        { 
            'Postman-Token': api._postmanToken,
            'cache-control': api._cache,
            'x-ccasset-language': 'en',
            Authorization: data.token
        },
        body: item,
        json: true 
    };

    return new Promise((resolve, reject) => {
        api._request(options, async (error, response, body) => {
            if(!response.body.errorCode && response.statusCode === 200) {
                payload = {
                    body: response.body,
                    type: data.req.body.type
                }
                dataProcessed = await db.saveProcessedData(payload);
            } else {
                payload = {
                    body: item,
                    type: data.req.body.type,
                    description: response.body.message
                }
                dataProcessed = await db.saveErrorData(payload);
            }

            if (error) {
                reject(error)
            }

            resolve(dataProcessed);
        });
    });
}

我怎样才能发现这个错误?

【问题讨论】:

  • 你使用的是request还是request-promise?
  • @MarcosCasagrande 请求承诺
  • 显示 api 是什么,特别是 api._request 定义。

标签: node.js request


【解决方案1】:

最好不要混合回调和承诺你正在做的方式。您收到该错误是因为您没有在 api._request 回调中正确处理错误。

将您的代码封装在try/catch 中的回调中,因为这是您在async 函数中处理异常的方式。

new Promise(async resolve => {
    await Promise.reject() // Unhandled Promise Rejection
}).catch(console.error) // not catched

应该是:

new Promise(async resolve => {
    try {
       await Promise.reject()
       resolve();
    } catch(e) {
       reject(e)
    }

}).catch(console.error) // catched

在任何情况下,既然您将 api._request 包装在 Promise 中,最好这样做:


const sendData = async(data, item) => {

    // ...

    const { error, response, body } = await new Promise((resolve, reject) => {
        api._request(options, (error, response, body) => resolve({ error, response, body }))
    })

    if(!response.body.errorCode && response.statusCode === 200) {
        payload = {
            body: response.body,
            type: data.req.body.type
        }
        dataProcessed = await db.saveProcessedData(payload);
    } else {
        payload = {
            body: item,
            type: data.req.body.type,
            description: response.body.message
        }
        dataProcessed = await db.saveErrorData(payload);
    }

    return dataProcessed;
}

并将.catch 处理程序附加到.sendData

除了在你的代码中,如果error 是真实的,你拒绝然后resolving,在这种情况下不会发生任何错误,但最好使用return reject()。一个承诺,不能被拒绝和解决。

if (error) {
   return reject(error)
}

resolve(dataProcessed);

如果您使用的是request,则可以使用request-promise 或request-promise-native,它们是request 包的Promise 包装器。

【讨论】:

    【解决方案2】:

    只是格式化

    const sendData = async (data, item) => {
    
        const options = {
            method: data.endpoint.method,
            url: api._url + data.endpoint.url,
            headers: {
                'Postman-Token': api._postmanToken,
                'cache-control': api._cache,
                'x-ccasset-language': 'en',
                Authorization: data.token
            },
            body: item,
            json: true
        };
    
        return Promise.resolve()
            .then(() =>
                new Promise((resolve, reject) => {
                    api._request(options, (error, response) => {
                        if (!response.body.errorCode && response.statusCode === 200) {
                            return resolve(
                                {
                                    body: response.body,
                                    type: data.req.body.type
                                }
                            );
    
                        }
                        return reject({
                            body: item,
                            type: data.req.body.type,
                            description: error || response.body.message
                        });
                    })
                }))
            .then(payload => db.saveProcessedData(payload))
            .catch(payload => db.saveErrorData(payload))
    }
    

    【讨论】:

      【解决方案3】:

      当您调用sendData() 时,您可以使用Promise.prototype.catch() 来捕获您的promise 中发生的异常,包括任何reject():

      sendData(myData, myItem)
          .then(result => {
              //do stuff with result 
          }
          .catch(error => {
              //handle error
          };
      

      【讨论】:

      • 你应该在 promise 上使用小写:promise.cache() 甚至yourPromise.catch(),它看起来像是构造函数上的静态方法。
      • 在我的答案描述中,我使用了带有大写 P 的 Promise,因为我指的是 Promise 的原型方法。
      • 这不是问题的全部,.catch 不会解决问题。检查我的答案。
      • 肯定会的。这个 .catch() 将捕获 sendData 承诺中抛出的任何异常。我自己也试过了。
      • @MichaelRodriguez 所以应该是Promise.prototype.catch,Promise.catch 不是一回事
      猜你喜欢
      • 2018-03-19
      • 2016-11-10
      • 2018-02-27
      • 1970-01-01
      • 2019-04-15
      • 1970-01-01
      • 2017-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多