【问题标题】:How to use promise bluebird in nested for loop?如何在嵌套 for 循环中使用 Promise bluebird?
【发布时间】:2015-07-31 20:47:52
【问题描述】:

我需要在我的代码中使用 bluebird,但我不知道如何使用它。我的代码包含嵌套循环。当用户登录时,我的代码将运行。它将开始查找用户下的任何文件,如果有文件,它将循环获取文件的名称,因为名称存储在字典中。一旦获得名称,它将将该名称存储在一个数组中。一旦存储了所有名称,它将在 res.render() 中传递。

这是我的代码:

  router.post('/login', function(req, res){
  var username = req.body.username;
  var password = req.body.password;
  Parse.User.logIn(username, password, {
    success: function(user){
      var Files = Parse.Object.extend("File");
      var object = [];
      var query = new Parse.Query(Files);
      query.equalTo("user", Parse.User.current());
      var temp;
      query.find({
        success:function(results){
          for(var i=0; i< results.length; i++){
            var file = results[i].toJSON();
            for(var k in file){
              if (k ==="javaFile"){
                for(var t in file[k]){
                 if (t === "name"){
                  temp = file[k][t];
                  var getname = temp.split("-").pop();
                  object[i] = getname;
                }
              }
            }
          }
        }
      }
    });
      console.log(object);
      res.render('filename', {title: 'File Name', FIles: object});
      console.log(object);
    },
    error: function(user, error) {
      console.log("Invalid username/password");
      res.render('logins');
    }
  })
});

编辑:代码不起作用,因为在第一个和第二个 console.log(object) 上,我得到一个空数组。我想在该数组中获取一项,因为我保存了一个文件

【问题讨论】:

  • 为什么需要使用bluebird?如果您将res.render 移动到最里面的success 回调的末尾,您的代码应该已经可以工作了
  • 代码不起作用,因为在第一个和第二个 console.log(object) 上,我得到一个空数组。我想在该数组中获取一项,因为我保存了一个文件。

标签: node.js parse-platform promise bluebird


【解决方案1】:

JavaScript 代码都是从上到下解析的,但它不一定以异步代码的顺序执行。问题是您在登录函数的成功回调中有日志语句,但它在查询的成功回调中NOT

你有几个选择:

  1. 将 console.log 语句移到内部成功回调中,以便在加载时解析它们,但在调用两个回调之前它们不会执行。
  2. Promisify 传统上依赖和调用回调函数的函数,然后将处理程序挂起返回值以将 Promise 链接在一起。

第一个选项根本不使用 Promise,而是完全依赖回调。为了扁平化你的代码,你需要promisify这些函数,然后将它们链接起来。

我不熟悉您在成功和错误回调中使用的语法,也不熟悉 Parse。通常你会做这样的事情:

query.find(someArgsHere, function(success, err) { 
});

但是你必须在其中嵌套另一个回调,并在其中嵌套另一个回调。为了“扁平化”金字塔,我们让函数返回一个promise,然后我们可以链接promise。假设 Parse.User.logIn 是一个回调样式函数(Parse.Query.find 也是如此),您可能会执行以下操作:

var Promise = require('bluebird');
var login = Promise.promisify(Parse.User.logIn);
var find = Promise.promisify(Parse.Query.find);
var outerOutput = [];

return login(yourArgsHere)
  .then(function(user) {
    return find(user.someValue);
  })
  .then(function(results) {
    var innerOutput = [];
    // do something with innerOutput or outerOutput and render it
  });

这对于您可能习惯的同步代码应该看起来很熟悉,除了不是将返回值保存到变量中然后将该变量传递给您的下一个函数调用,您使用“then”处理程序将 Promise 链接在一起。您可以在第二个 then 处理程序中创建整个输出变量,也可以在启动此承诺链之前声明变量输出,然后它将在所有这些函数的范围内。我已经向您展示了上面的两个选项,但显然您不需要定义这两个变量并为它们赋值。只需选择适合您需求的选项即可。

您还可以使用 Bluebird 的 promisifyAll() 函数将整个库与等效的 promise-returning 函数包装起来。它们都将具有与库中以 Async 为后缀的函数的相同名称。因此,假设 Parse 库包含名为 someFunctionName() 和 someOtherFunc() 的回调样式函数,您可以这样做:

var Parse = Promise.promisifyAll(require("Parse"));
var promiseyFunction = function() {
  return Parse.someFunctionNameAsync()
    .then(function(result) {
      return Parse.someOtherFuncAsync(result.someProperty);
    })
    .then(function(otherFuncResult) {
      var something;
      // do stuff to assign a value to something
      return something;
    });
}

【讨论】:

    【解决方案2】:

    我有几点建议。 ...顺便说一句,您是否尝试使用 Parse 的 Promises?

    您可以摆脱那些内部嵌套循环和一些其他更改:

    使用类似这样的语法更优雅:

    /// You could use a map function like this to get the files into an array of just thier names
    var fileNames = matchedFiles.map(function _getJavaFile(item) {
        return item && item.javaFile && item.javaFile.name // NOT NULL
          && item.javaFile.name.split('-')[0]; // RETURN first part of name
    });
    
    
    // Example to filter/retrieve only valid file objs (with dashes in name)
    var matchedFiles = results.filter(function _hasJavaFile(item) {
        return item && item.javaFile && item.javaFile.name // NOT NULL
             && item.javaFile.name.indexOf('-') > -1; // and has a dash
    });
    

    这里是一个使用 Parse 原生 Promise 的示例(将上面的代码添加到下面的第 4/5 行,注意 'then()' 函数,它现在实际上是你的 'callback' 处理程序):

    var GameScore = Parse.Object.extend("GameScore");
    var query = new Parse.Query(GameScore);
    query.select("score", "playerName");
    query.find().then(function(results) {
      // each of results will only have the selected fields available.
    });
    

    【讨论】:

    • 你的代码一口气做了太多不同的动作。我将用更多代码编辑我的答案...
    猜你喜欢
    • 1970-01-01
    • 2020-09-17
    • 2017-08-08
    • 2018-10-01
    • 2022-12-09
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    相关资源
    最近更新 更多