代码之家  ›  专栏  ›  技术社区  ›  LizG

嵌套警告-避免嵌套问题

  •  1
  • LizG  · 技术社区  · 7 年前

    我尝试过解决嵌套问题,但我用过的东西都不管用,甚至没有 Google Cloud Functions - warning Avoid nesting promises promise/no-nesting .

    exports.payout = functions.https.onRequest((request, response) => {
    var uid = "nYIAHSYimJMHbMkXqDt9PQ0U3Nf2";
    
    getPayoutsPending(uid).then((array) => {
        getPayoutsAmount(array).then((value) => { **// avoid nesting promises**  
            var valueTrunc = parseFloat(Math.round(value * 100) / 100).toFixed(2);
    
            const sender_batch_id = Math.random().toString(36).substring(9);
            const sync_mode = 'false';
            const payReq = JSON.stringify({
                sender_batch_header: {
                    sender_batch_id: sender_batch_id,
                    email_subject: "You have a payment"
                },
                items: [
                    {
                        recipient_type: "EMAIL", 
                        amount: {
                            value: valueTrunc,
                            currency: "CAD"
                        },
                        receiver: "me@gmail.com",
                        note: "Thank you.",
                        sender_item_id: "Payment"
                    }
                ]
            });
    
            paypal.payout.create(payReq, sync_mode, (error, payout) => {
                if (error) {
                    console.warn(error.response);
                    response.status('500').end();
                    throw error;
                } else {
                    console.info("payout created");
                    console.info(payout);
    
                    **// avoid nesting problems** 
                    updatePaymentsPending(uid, sender_batch_id).then(() => {
                        response.status('200').end();
                        return;
                    }).catch((error) => {
                        return console.error(error);
                    })
                }
            });
            return null;
        }).catch((error) => {
            return console.error(error);
        })
        return null;
    }).catch((error) => {
        return console.error(error);
    })
    
    });
    

    标记的线条

    编辑-答案结果

    screenshot of Terminal

    第111:20行显示:

    第120:21行显示:

    编辑#2

    将代码更改为@imjared提供的代码后,我得到以下错误:

    ReferenceError: sender_batch_id is not defined
    at exports.payout.functions.https.onRequest (/user_code/index.js:136:40)
    at cloudFunction (/user_code/node_modules/firebase-functions/lib/providers/https.js:57:9)
    at /var/tmp/worker/worker.js:689:7
    at /var/tmp/worker/worker.js:673:9
    at _combinedTickCallback (internal/process/next_tick.js:73:7)
    at process._tickDomainCallback (internal/process/next_tick.js:128:9)
    

    然后:

    Function execution took 1327 ms, finished with status: 'crash'
    

    ReferenceError: paymentRequest is not defined
    at Promise (/user_code/index.js:111:17)
    at buildPaymentRequest (/user_code/index.js:90:14)
    at process._tickDomainCallback (internal/process/next_tick.js:135:7)
    

    编辑#3-destenson post的回复

    我的代码是:

    exports.payout = functions.https.onRequest((request, response) => {
    return getPayoutsPending(request.body.uid)
        .then(array => getPayoutsAmount(array))
        .then(value => {
            var valueTrunc = parseFloat(Math.round(value * 100) / 100).toFixed(2);
            const sender_batch_id = Math.random().toString(36).substring(9);
            const sync_mode = 'false';
            const payReq = JSON.stringify({
                sender_batch_header: {
                    sender_batch_id: sender_batch_id,
                    email_subject: "You have a payment"
                },
                items: [
                    {
                        recipient_type: "EMAIL",
                        amount: {
                            value: valueTrunc,
                            currency: "CAD"
                        },
                        receiver: request.body.email,
                        note: "Thank you.",
                        sender_item_id: "Payment"
                    }
                ]
            });
    
            return paypal.payout.create(payReq, sync_mode, (error, payout) => {
                if (error) {
                    console.warn(error.response);
                    response.status('500').end();
                    throw error;
                }
                console.info("payout created");
                console.info(payout);
                return updatePaymentsPending(request.body.uid, sender_batch_id)
            }).then(() => {
                response.status('200').end();
                return null;
            });
        })
        .catch(error => {
            console.error(error);
        });
    });
    

    执行应用程序时,函数日志显示:

    TypeError: Cannot read property 'then' of undefined
    at getPayoutsPending.then.then.value (/user_code/index.js:120:15)
    at process._tickDomainCallback (internal/process/next_tick.js:135:7)
    

        { batch_header: 
       { payout_batch_id: '*************',
         batch_status: 'PENDING',
         sender_batch_header: 
          { sender_batch_id: '************',
            email_subject: 'You have a payment' } },
      links: 
       [ { href: 'https://api.sandbox.paypal.com/v1/payments/payouts/*******',
           rel: 'self',
           method: 'GET',
           encType: 'application/json' } ],
      httpStatusCode: 201 }
    

    然后:

    uncaught exception
    

    ReferenceError: uid is not defined
    at paypal.payout.create (/user_code/index.js:119:46)
    at IncomingMessage.<anonymous> (/user_code/node_modules/paypal-rest-sdk/lib/client.js:140:13)
    at emitNone (events.js:91:20)
    at IncomingMessage.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:80:11)
    at process._tickDomainCallback (internal/process/next_tick.js:128:9)
    

    最后:

    Function execution took 1517 ms, finished with status: 'crash'
    

    执行应用程序后,函数的以下日志为:

    screenshot of function logs

    2 回复  |  直到 6 年前
        1
  •  2
  •   Dennis Estenson    7 年前

    我将通过链接承诺来解决这个问题,而不是嵌套它们。当您从 then() 回调,它成为一个新的承诺,然后可以再次使用。

    我没有测试过您的代码的这个修改版本,但我希望您能了解其中的要点:

    exports.payout = functions.https.onRequest((request, response) => {
        var uid = "nYIAHSYimJMHbMkXqDt9PQ0U3Nf2";
    
        return getPayoutsPending(uid)
            .then(array => getPayoutsAmount(array))
            .then(value => {
                var valueTrunc = parseFloat(Math.round(value * 100) / 100).toFixed(2);
                const sender_batch_id = Math.random().toString(36).substring(9);
                const sync_mode = 'false';
                const payReq = JSON.stringify({
                    sender_batch_header: {
                        sender_batch_id: sender_batch_id,
                        email_subject: "You have a payment"
                    },
                    items: [
                        {
                            recipient_type: "EMAIL",
                            amount: {
                                value: valueTrunc,
                                currency: "CAD"
                            },
                            receiver: "me@gmail.com",
                            note: "Thank you.",
                            sender_item_id: "Payment"
                        }
                    ]
                });
    
                return paypal.payout.create(payReq, sync_mode, (error, payout) => {
                    if (error) {
                        console.warn(error.response);
                        response.status('500').end();
                        throw error;
                    }
                    console.info("payout created");
                    console.info(payout);
                    return updatePaymentsPending(uid, sender_batch_id)
                });
            }).then(() => {
                response.status('200').end();
                return null;
            }).catch(error => {
                console.error(error);
            });
    });
    

    我希望这有帮助。

    编辑:成功的案例缺少返回null。我猜你的衣帽匠对此很挑剔。

    .

        2
  •  1
  •   imjared    7 年前

    同样未经测试,但基于eslint的目标似乎是取消所有嵌套。这有点麻烦,但我想这是可行的。

    exports.payout = functions.https.onRequest((request, response) => {
      var uid = "nYIAHSYimJMHbMkXqDt9PQ0U3Nf2";
    
      // Returns paymentRequest
      const buildPaymentRequest = (value) => {
        return new Promise((resolve) => {
          var valueTrunc = parseFloat(Math.round(value * 100) / 100).toFixed(2);
    
          const sender_batch_id = Math.random().toString(36).substring(9);
          const sync_mode = 'false';
          const payReq = JSON.stringify({
            sender_batch_header: {
              sender_batch_id: sender_batch_id,
              email_subject: "You have a payment"
            },
            items: [{
              recipient_type: "EMAIL",
              amount: {
                value: valueTrunc,
                currency: "CAD"
              },
              receiver: "me@gmail.com",
              note: "Thank you.",
              sender_item_id: "Payment"
            }]
          });
          resolve(paymentRequest);
        });
      }
    
      // Returns payout
      const createPayout = (paymentRequest) => {
        return new Promise((resolve, reject) => {
          paypal
            .payout
            .create(payReq, sync_mode, (error, payout) => {
              if (error) {
                console.warn(error.response);
                reject(error);
              } else {
                console.info("payout created");
                resolve(payout);
              }
            });
        });
      };
    
      getPayoutsPending(uid)
        .then(getPayoutsAmount)
        .then(buildPaymentRequest)
        .then(createPayout)
        .then(updatePaymentsPending(uid, sender_batch_id))
        .then(() => {
          response.status('200').end();
          return;
        })
        .catch((err) => {
          console.log(err);
          response.status('500').end();
          return console.error(error);
        })
    });
    

    或者,抛出 // eslint-disable 在文件的顶部可以解决您的问题;)