如何从嵌套的Promise函数返回Promise对象

时间:2018-08-01 21:55:50

标签: javascript node.js promise bluebird request-promise

我很难理解Promises的工作方式。在基础上,我了解resolvereject.catch ()是什么。

但是,我正在尝试创建一个Promise函数(使用Bluebird),该函数本身使用另一个Promise函数,并且我想从此嵌套的Promise函数中返回解析或拒绝。所以我做了以下事情:

FacebookMes​​sengerAPI.js

const request = require("request-promise");
const Prom = require("bluebird");

exports.send = (sender_psid, response) => {

    return Prom.try(() => {
        if (sender_psid == null || sender_psid == undefined || sender_psid == "") {
            console.error("Invalid sender_psid: \t" + sender_psid);
            let error = {
                code : errorCodes.ERR_INVALID_PARAMETER,
                message : "Invalid sender_psid value"
            }
            return Prom.reject(error); // This works fine
        }

        if (response == null || response == undefined) {
            console.error("Response body is either null or undefined:\t" + response);
            let error = {
                code : errorCodes.ERR_INVALID_PARAMETER,
                message : "Response is either null or undefined"
            }
            return Prom.reject(error); // This also works fine
        }

        let options = {
            url : appConstants.URL_FACEBOOK_GRAPH_API,
            qs : { access_token : appConstants.TOKEN_PAGE_ACCESS },
            method : "POST",
            body : response,
            json : true
        };

        request(options)
            .then((responseBody) => {
                console.log("ResponseBody: \t" + responseBody);
            }, (rejected) => {
                if (rejected.error.error.message) {
                    let error = {
                        code : errorCodes.ERR_FB_GRAPH_API,
                        message : rejected.error.error.message
                    }
                    throw error; // This is where things go wrong
                }

            })
            .catch((err) => {
                console.error("Error while calling FB Graph API:\n" + err);
                let error = {
                    code : errorCodes.ERR_UNMAPPED_ERROR,
                    message : err
                };
            });
    });

}

TestApp.js -调用此API的人

"use strict";

const facebookMessengerApi = require("./service/FacebookMessengerApi");

facebookMessengerApi.send(1111,1111).then((resolved) => {
    if (resolved) {
        console.log("Resolves ==> ",resolved);
    }
}, (rejected) => {
    if (rejected) {
        console.log("Rejected:\t" + someshit);
        throw new Error("An err thrown here")
    }
}).catch((error) => {
    console.error("ERRORIFIED:\n\n" + error);
});

这里的问题是,我不知道如何从request函数将Promise对象发送到父Promise函数,该函数本身是Promise函数,并且嵌套在父Promise函数中。

解决/拒绝请求功能时:

  1. 当我用throw new error抛出错误时,它被捕获在.catch函数的直接request块中。它永远不会传递给该API的实际调用者

  2. 当我使用Prom.reject(error)时,会收到unhandled rejection警告,尽管我不知道确切的地方,因为我在request中都处理过方法以及此API的调用程序中。除此之外,Prom.reject(error)实际上以.catch()函数的request块结尾,而不是调用者函数的结尾。

1 个答案:

答案 0 :(得分:1)

注意:

  • 根据定义,您正在拒绝,这是一个Promise失败(即另一个拒绝
  • 在Promise链上执行.catch()时,它会恢复链
    • 这意味着在捕获之后,当前或父链中的下一个.then()现在将获得从catch语句返回的任何内容。
    • 因此,您应该:
      • 在最后运行catch,因此之后无需再进行任何处理
      • 和/或弹跳异常,通过再次考虑/拒绝,直到触发下一个catch语句
  • 根据返回的内容,承诺的行为有所不同:
    • <Promise>:等待完成,使用链中下一个.then()中的值
    • Not a promise:使用返回值作为下一个.then()
    • 的输入
    • <Exception>:并不是真正的回报,但会导致它返回到下一个catch(e),其中e是异常消息
    • <Rejection>:来自具有拒绝或Promise.reject(e)作为返回值的子链。继续下一个.catch(e)

TL; DR-除非其中有例外或拒绝,否则.then / .catch的输出将始终是下一个.then()的输出。 。在这种情况下,下一个.catch()将被触发

解决方案/重构

// Using standard promises
const prBody = _ => {
    if (sender_psid == null || sender_psid == undefined || sender_psid == "") {
        console.error("Invalid sender_psid: \t" + sender_psid);
        let error = {
            code : errorCodes.ERR_INVALID_PARAMETER,
            message : "Invalid sender_psid value"
        }
        throw error
    }

    if (response == null || response == undefined) {
        console.error("Response body is either null or undefined:\t" + response);
        let error = {
            code : errorCodes.ERR_INVALID_PARAMETER,
            message : "Response is either null or undefined"
        }
        throw error // This also works fine
    }

    let options = {
        url : appConstants.URL_FACEBOOK_GRAPH_API,
        qs : { access_token : appConstants.TOKEN_PAGE_ACCESS },
        method : "POST",
        body : response,
        json : true
    };
    
    // Return a promise which needs to then be resolved for the next thing in the chain to get the data
    return request(options)
        .then(responseBody => {
            console.log("ResponseBody: \t" + responseBody)
            return responseBody
        })
        .catch(errorObj => {
            if (!errorObj.error.error.message) return
            let error = {
                code : errorCodes.ERR_FB_GRAPH_API,
                message : rejected.error.error.message
            }
            throw error; // This is where things go wrong
        })
        // This is going to be the exception you triggered in the previous catch block
        .catch(err => {
            console.error("Error while calling FB Graph API:\n" + err);
            let error = {
                code : errorCodes.ERR_UNMAPPED_ERROR,
                message : err
            };
        });
})
return Promise.resolve()
    .then(prBody)
    .then(responseBodyORError => {
        if (responseBodyORError.error) {return console.log('There was an error, catch simply recover chains')}
        // At this point responseBodyORError will only be the response body, since error checking is done
    })