简体   繁体   English

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

[英]How to return a Promise object from a nested Promise function

I'm having a hard time understanding how Promises work. 我很难理解Promises的工作方式。 At the base, I understand what resolve , reject and .catch () are. 在基础上,我了解什么是resolvereject.catch ()

However, I am trying to create a Promise function (using Bluebird ) that itself uses another Promise function and I want to return a resolve or reject from this nested Promise function. 但是,我试图创建一个Promise函数(使用Bluebird ),该函数本身使用另一个Promise函数,并且我想从嵌套的Promise函数中返回一个解决方法或拒绝该方法。 So I have done the following: 所以我做了以下工作:

FacebookMessengerAPI.js 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 -- the guy that calls this API 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);
});

The problem here is, I don't know how to send a Promise object to the parent Promise function from the request function that itself is a Promise function and is nested inside the parent Promise function. 这里的问题是,我不知道如何从本身是Promise函数并嵌套在父Promise函数内部的request函数中将Promise对象发送到父Promise函数。

On resolve / reject of the request function: 在解决/拒绝请求功能时:

  1. When I throw the error by throw new error , it is caught in the immediate .catch block of the request function. 当我通过throw new error错误来throw new error ,它被捕获在request函数的直接.catch块中。 It never goes to the actual caller of this API 它永远不会传递给该API的实际调用者

  2. When I use Prom.reject(error) , I get unhandled rejection warning although I don't know exactly where I'm not handling it since I have handled it both in the request method as well as in the caller of this API. 当我使用Prom.reject(error) ,我得到了unhandled rejection警告,尽管我不知道确切的地方,因为我已经在request方法以及此API的调用Prom.reject(error)对其进行了处理。 Along with that, the Prom.reject(error) actually ends up in the .catch() block of the request function and not in that of the caller function. 除此之外, Prom.reject(error)实际上以request函数的.catch()块结尾,而不是调用者函数的块结尾。

Notes: 笔记:

  • You're doing a throw in your rejection, by definition that's a Promise failure ( ie. another rejection ) 根据定义,这是一次Promise失败( 即另一次拒绝 ),因此您正在抛出拒绝
  • When you do a .catch() on a Promise chain, it recovers the chain 在Promise链上执行.catch()时,它会恢复链
    • This means after a catch, the next .then() in the current or parent chain, will now get whatever was returned from the catch statement. 这意味着在catch之后,当前或父链中的下一个.then()现在将获得catch语句返回的所有内容。
    • Because of this you should either: 因此,您应该:
      • Run catch at the very end, so there is no more processing done after it 在最后运行catch,因此之后无需再进行其他处理
      • And/or ricochet the exception, by thowing / rejecting again, till the next catch statement is triggered 和/或弹跳异常,通过再次考虑/拒绝,直到触发下一个catch语句
  • Promises behave differently depending on what is returned: 承诺的行为取决于返回的内容:
    • <Promise> : Wait till complete, use value in the next .then() in the chain <Promise> :等到完成,在链中的下一个.then()中使用值
    • Not a promise : Use the return value as the input for the next .then() Not a promise :将返回值用作下一个.then()的输入
    • <Exception> : Not really a return, but will cause it to go to the next catch(e) , where e is the exception message <Exception> :并非真正的返回值,但会导致它返回到下一个catch(e) ,其中e是异常消息
    • <Rejection> : Comes from a sub-chain having a rejection, or Promise.reject(e) as a return value. <Rejection> :来自具有拒绝或Promise.reject(e)作为返回值的子链。 Continue to the next .catch(e) 继续下一个.catch(e)

TL;DR - The output of .then / .catch will always be the output for the next .then() unless there is an exception or rejection in them. TL; DR -的输出.then / .catch将始终为下一个的输出.then()除非在它们的异常或拒绝。 In which case the next .catch() will be triggered 在这种情况下,下一个.catch()将被触发

Solution / Refactor 解决方案/重构

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM