【问题标题】:How to chain promises returned from multiple files in nodejs如何链接从nodejs中的多个文件返回的承诺
【发布时间】:2018-10-05 06:21:33
【问题描述】:

我正在尝试编写一个 Lambda 代码,我尝试在 DynamoDB 中创建多个条目,如果失败,我将一条错误消息放入 SQS。我正在尝试使用 Promises 来做到这一点。

我的 DDB.js 文件

var AWS = require('aws-sdk');

exports.operation = function(ddbEvent) {
    var dynamoDB = new AWS.DynamoDB();
    var params = {};

    var operation = ddbEvent.operation;
    switch(operation) {
        case 'insert':
        case 'modify':
            params["Item"] = ddbEvent.entry;
            //Fill in params object from ddbEvent;

            return dynamoDb.putItem(params, function(err, data) {
                //Nothing to do just log
                if(err) {
                    //log error msg
                } else {
                    //log success
                }
            }).promise();

        case 'delete':
            //Do nothing operation
            return Promise.resolve();

        default:
            console.warn("unsupported");
    }
};

我的 SQS.js 文件:

var AWS = require('aws-sdk');

exports.sqsOperation = function(message) {
    var sqs = new AWS.SQS({

    });

    var params = {
        //Use message to form the body
    };

    return sqs.sendMessage(params, function(err, data) {
        //Nothing to do just log like in DDB.js
    }).promise();
};

我的 main.js 文件(调用了 Lambda):

var AWS = require('aws-sdk');
var SQS = require('SQS');
var DDB = require('DDB');


    exports.replicate = function(event, context, callback) {
        var ddbPromise = [];
        var sqsPromise = [];

        event.Records.forEach((entry) => {
            let p = DDB.operation(entry);
            ddbPromise.push(p);
            p.then(function(data) {
                //write to ddb succssfull;
            }).catch(function (err) {
                //ddb save failed, try writing to sqs.
                let sqsP = SQS.sqsOperation(entry);
                sqsPromise.push(sqsP);
                sqsP.then(function (data) {
                    //push to sqs success
                }).catch(function (err) {
                    //push to sqs failed
                });
            });
        });

        var ddb_promises_all = Promise.all(ddbPromise);

        ddb_promises_all.then(function (data) {
            //all entries saved in DDB 
            callback(null, "success");
        }).catch(function (err) {
            //Now repeat wait for all sqs promises. If any sqs push failed then
            //use callback(new Error("error"));
        });
    }

可以看出,promise 和回调模式混合在一起。我遇到了一个名为 bluebird 的库,它可以帮助避免这个问题。那会是更好的方法吗?有没有更好的方法来链接这些承诺,因为我觉得将状态保存在数组中似乎是一种错误的做法,如果使用 bluebird,强制从回调模式返回承诺会更整洁。

【问题讨论】:

    标签: node.js aws-lambda es6-promise bluebird


    【解决方案1】:

    对于你的情况,我更喜欢用一些方法来提取它们,比如

    exports.replicate = function(event, context) {
      // if possible, use Promise for consistency
      return new Promise((resolve, reject) => {
    
        // I feel that using `map` is cleaner than `forEach`
        const ddbOperationPromises =  event.Records.map(entry => ddbOperation(entry));
    
        return Promise.all(ddbOperationPromises)
          .then(data => {
            // success
            resolve();
          })
          .catch(err => {
            // catch error
          })
      });
    }
    
    function ddbOperation(entry) {
      return DDB.operation(entry)
        .then((data) => {
          // success
        })
        .catch((err) => {
          return sqsOperation(entry);
        })
    }
    
    function sqsOperation(entry) {
      return SQS.sqsOperation(entry)
        .then((data) => {
          // success
        })
        .catch((err) => {
          // handling err
        })
    }
    

    【讨论】:

    • 谢谢。在这种情况下如何返回回调?在我的 sn-p 中,我使用 callback() 来返回,但是由于您使用的是 Promise,所以回调方法不可用。
    • 或者你的意思是使用,reject(new Error("error"));还有一种方法可以使用 Bluebird 来 promsify DDB 和 SQS 文件,而不是在那里使用回调模式?
    • 我没玩过 lambda。 exports.replicate 必须回调吗?在这里使用回调的原因是什么?对于 DDB 和 SQS,您已经通过调用 .promise() 将回调转换为 Promise 来使用 Promise。
    【解决方案2】:

    异步等待救援 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

    async function doDBStuff (...)
    async function doOtherStuff (...)
    
    async function doSequentially () {
      await doDBStuff(...);
      await doOtherStuff(...);
    }
    
    async function doInParallel () {
      await Promise.all([doDBStuff(...), doOtherStuff(...)]);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-27
      • 2016-05-18
      • 1970-01-01
      • 1970-01-01
      • 2018-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多