如何在嵌套的for循环中使用promise bluebird?

How to use promise bluebird in nested for loop?

我需要在我的代码中使用 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) 上,我得到一个空数组。我想在那个数组中得到一个项目,因为我保存了一个文件

我有几点建议。 ...顺便说一句,您是否正在尝试使用 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 的本机承诺的示例(将上面的代码添加到下面的第 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.
});

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

您有几个选择:

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

第一个选项根本不使用 promises,而是完全依赖回调。要扁平化您的代码,您需要对函数进行承诺,然后将它们链接起来。

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

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

但是你必须在其中嵌套另一个回调,然后在其中嵌套另一个回调。对于 "flatten" 金字塔,我们将函数 return 改为一个承诺,然后我们可以链接这些承诺。假设 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
  });

这对于您可能习惯的同步代码应该看起来很熟悉,除了不是将 returned 值保存到变量中然后将该变量传递给下一个函数调用,而是使用 "then" 处理程序将承诺链接在一起。您可以在第二个 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;
    });
}