【问题标题】:How do you call a function with parameters in a .then function in a JavaScript promise string?如何在 JavaScript 承诺字符串中的 .then 函数中调用带有参数的函数?
【发布时间】:2017-03-25 02:40:56
【问题描述】:

我正在转换我用 node.js 编写的 AWS lambda 函数,以使用 Promise 而不是回调。我用处理程序代码将我的所有函数包装在处理程序中。我正在尝试分解简单的函数,以便我可以在处理程序代码中拥有尽可能平坦的承诺链。

我被困在一个点上,我有一个 .then(),它返回一个值,我需要传递给我的一个函数,该函数已被承诺,以及其他参数。我搜索了高和低,但找不到执行此操作的语法示例。我什至不确定我在做什么是正确的。我发现的所有文章都解释了仅通过 .then() 方法返回值的简单承诺链。 None 将其传递给另一个 promisified 函数。

这是我目前所拥有的:

var bbPromise = require("./node_modules/bluebird");
var AWS = require("./node_modules/aws-promised");
var rp = require("./node_modules/request-promise");
var moment = require('./node_modules/moment.js');
var dynamodb = new AWS.dynamoDb();

exports.handler = function(event, context) { 
    "use-strict"; 

    // This gets a token that will be used as a parameter for a request
    function getToken(params){
        return rp.post({
            url: "https://api.something.com/oauth2/token",
            followRedirects: true,
            form: params,
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        }).then(function(body){
            return JSON.parse(body).access_token;
        }).catch(function(error){
            console.log("could not get token: "+error);
        });
    }

    function getData(userId, db, token){ 
        var qParams = {
            // params that will get one record 
        };
        return dynamodb.queryPromised(qParams)
        .then(function (data){
            var start_date = // did some date manipulation on data to get this value
            // Request records, passing the token in the header
            var url = "https://api.something.com/data/?db="+db+"&start_date="+start_date;
            var headers = {
              'Content-Type': 'application/x-www-form-urlencoded',
              'Authorization':'Bearer '+token
            };
            tokenParams = {all the parameters};
            rp.get({
                url:url, 
                qs:tokenParams, 
                headers:headers, 
                followRedirect: true
            }).then(function(body){
                return body;
            }).catch(function(error){
                console.log("could not get data: "+error);
            });
        }).catch(function(error){
            console.log("Final Catch - getData failed: "+error);
        });
    }

    // THIS IS WHERE THE HANDLER CODE STARTS

    // Get an array of all userIds then get their data
    dynamodb.scanPromised({
        // params that will get the user Ids
    }).then(function(users){
        for(var i=0; i<users.length; i++){
            userId = // the value from the user record;        
            // Request a token
            var tokenParams = {an object of params};
            getToken(tokenParams)
            .then(function(token){
            ///////////// THIS IS WHERE I NEED HELP /////////////////
            /* Is there a way to pass getData the token within the .then() so I don't have a nested promise? */
                getData(userId, users[i].dbName, token)

            //////////////////////////////////////////////////////////
            }).catch(function (e){
                console.log("caught an error");
            });
        }
    }).catch(function (e){
        console.log("caught an error");
    });
};

【问题讨论】:

  • 你在那里使用了一个循环。您将需要嵌套。这也没有什么问题。
  • 刚刚做的有什么问题:getData(userId, users[i].dbName, token).then(function (data) { /* handle the data here */ })?
  • 我正试图弄清楚如何将 getData 调用放入之前的 .then() 中。
  • 我认为如果你使用类似 co 和 generators npmjs.com/package/co 的东西,你会发现开始使用 Promise 会容易得多

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


【解决方案1】:

您可以使用Promise.all().then()Function.prototype.bind()returnrp.get()来自getData()

 return Promise.all(users.map(function(user) {
   userId = // the value from the user record;        
     // Request a token
     var tokenParams = {
       an object of params
     };
   return getToken(tokenParams)
     .then(getData.bind(null, userId, user.dbName))
     .catch(function(e) {
       console.log("caught an error");
       throw e
     });
 }))

【讨论】:

  • 这个答案解决了主要问题,但是原始问题中还有另一个流程:不要忘记return rp.get
  • 这个答案可能是我正在寻找的,但我有点困惑。这种语法会自动将 getToken 返回的令牌传递给 getData 吗?如果是这样,作为什么参数?它会代替空参数吗?
  • @user3353762 是的。作为getData() 的最后一个参数
  • 我无法完成这项工作。当我将 null 作为第一个参数传递时,然后在 getData 中,userId 获取 null 值,dbName 获取 userId 值,并且 token 未定义。如果我将“令牌”作为第三个参数传递给 getData,它仍然是未定义的。我仍然对如何将 getToken 的返回值传递给 .then 括号内的 getData 感到困惑。
【解决方案2】:

使用 Promise 时,您的代码应该看起来更像这样。

when.try(() => {
    return api.some_api_call
})
.then((results) => {
    const whatIAmLookingFor = {
        data: results.data
    };

    someFunction(whatIAmLookingFor);
})
.then(() => {
    return api.some_other_api_call
})
.then((results) => {
    const whatIAmLookingFor = {
        data: results.data
    };

    someOtherFunction(whatIAmLookingFor); 
.catch(() => {
    console.log('oh no!');
})
});

【讨论】:

  • 承诺嵌套是完全允许的,而且通常是完全必要的。例如,在上面,如果api.some_other_api_call() 返回一个承诺,它的最终值(或错误)将被传递到以下.then() 的结算回调。 Promises/A+ specification 中的承诺解决程序是专门为此设计的。看看几个例子——你会发现到处都是嵌套的 Promise。
猜你喜欢
  • 1970-01-01
  • 2016-12-06
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-29
相关资源
最近更新 更多