【问题标题】:javascript - then/ promises can't use variable after for loopjavascript - then/promise 不能在 for 循环后使用变量
【发布时间】:2014-12-26 00:58:21
【问题描述】:

我有这段代码,但我无法在 for 循环之外使用这个 userArray,不知道为什么它什么都不返回,这里是代码:

Parse.Cloud.define("test", function(request, response) {

var UserFavourite = Parse.Object.extend("UserFavourite");
var queryFavourite = new Parse.Query(UserFavourite);

var userArray = [];
var TestItem = Parse.Object.extend("TestItem");
var query = new Parse.Query(TestItem);
query.limit(1000);
query.equalTo('school', 'Union College (NY)');
query.find().then(function(results) {
    return results;


}).then(function(results) {
    for (var i = 0; i < results.length; i++) { 
        var object = results[i];
        var item = object.get('item');
        var school = object.get('school');
        var meal = object.get('meal');

        var UserFavourite = Parse.Object.extend("UserFavourite");
        var queryFavourite = new Parse.Query(UserFavourite);
        queryFavourite.equalTo("item", item);
        queryFavourite.equalTo("school", school);
        queryFavourite.find().then(function(users) {
            for (var i = 0; i < users.length; i++) {
                var user = users[i];
                var userID = user.get('user').id;
                if (userArray.indexOf(userID) === -1) {
                    userArray.push(userID);
                }
//                  console.log(userArray);
                return userArray;
            }
            return userArray;


        });            
        console.log('sadf '+userArray);
    }
    console.log('sadf '+userArray);
    return userArray;


}).then(function() {
    console.log(userArray);
});

我已经查看了这个,但我似乎仍然能够在最后一个函数或之前的两个 console.log 中获取 userArray

How do I return the response from an asynchronous call?

提前感谢您的帮助。

【问题讨论】:

  • 因为queryFavourite.find()也是异步的..
  • @ArunPJohny 对,但我使用了.then,所以它应该等到它完成对吗?
  • then() 将等待调用它的承诺完成......在这种情况下,外承诺在内部承诺之前完成
  • @ArunPJohny 好的,我该如何解决这个问题?有什么想法吗?

标签: javascript ajax parse-platform promise


【解决方案1】:

注意:这不是经过测试的代码......但解决方案是使用一个承诺,一旦循环中的所有承诺完成,该承诺将被解决

var UserFavourite = Parse.Object.extend("UserFavourite");
var queryFavourite = new Parse.Query(UserFavourite);

var userArray = [];
var TestItem = Parse.Object.extend("TestItem");
var query = new Parse.Query(TestItem);
query.limit(1000);
query.equalTo('school', 'Union College (NY)');
query.find().then(function (results) {
    return results;
}).then(function (results) {
    var promises = [];
    for (var i = 0; i < results.length; i++) {
        var object = results[i];
        var item = object.get('item');
        var school = object.get('school');
        var meal = object.get('meal');

        var UserFavourite = Parse.Object.extend("UserFavourite");
        var queryFavourite = new Parse.Query(UserFavourite);
        queryFavourite.equalTo("item", item);
        queryFavourite.equalTo("school", school);
        var prom = queryFavourite.find().then(function (users) {
            for (var i = 0; i < users.length; i++) {
                var user = users[i];
                var userID = user.get('user').id;
                if (userArray.indexOf(userID) === -1) {
                    userArray.push(userID);
                }
                //                  console.log(userArray);
                return userArray;
            }
            return userArray;
        });
        promises.push(prom);
        console.log('sadf ' + userArray);
    }
    console.log('sadf ' + userArray);
    return Parse.Promise.when.apply(Parse.Promise, promises);
}).then(function () {
    console.log(userArray);
});

这里我们要做的是在循环中创建一个promise数组,将其传递给.when()以返回一个promise,当所有传递给它的promise完成时,该promise将被解析。

所以根据定义,最后一个 then() 应该得到更新的 userArray - 测试并告诉我它是否有效

【讨论】:

    【解决方案2】:

    APJ 所说的似乎 100% 正确,但是通过避免不必要的分配,并结合使用链接和明智地使用 array.map()array.reduce(),您可以大大减少代码量。

    眼睛对准array.map()array.reduce() 的人甚至可能会发现可读性有所提高。

    模式的核心是:

    (new Parse.Query(...))...find().then(function(results) {
        return Parse.Promise.when(results.map(function(obj) { // map results to a new array, and return it.
            return (new Parse.Query(...))...find().then(function(users) {
                return users.map(...); // map users to a new array, and return it.
            });
        })).then(function() {// each argument to this function is an array of ids
            // process `arguments` to form a single array of unique ids, and return it.
        });
    });
    

    全文:

    Parse.Cloud.define("test", function(request, response) {
        (new Parse.Query(Parse.Object.extend("TestItem")))
            .limit(1000)
            .equalTo('school', 'Union College (NY)')
            .find().then(function(results) {
                return Parse.Promise.when(results.map(function(obj) {
                    return (new Parse.Query(Parse.Object.extend("UserFavourite")))
                        .equalTo("item", obj.get('item'))
                        .equalTo("school", obj.get('school'))
                        .find().then(function(users) {
                            return users.map(function(user) {
                                return user.get('user').id; // duplicates are filtered out below
                            });
                        });
                })).then(function() {
                    return Array.prototype.slice.apply(arguments).reduce(function(p, c) { // reduce an array of arrays to a single array
                        return p.concat(c);
                    }).filter(function(value, idx, self) { // filter out duplicates
                        return self.indexOf(value) === idx;
                    });
                });
        }).then(function(userArray) { // named member `userArray` appears for the first time at this point
            console.dir(userArray);
        });
    });
    

    未经测试

    您将看到所需的数组不是直接组成的,而是从一组 promise 派生的,每个 promise 都传递一个 userID 数组。

    在性能方面,采用这种方法有利有弊。如果没有测试,我不能说它会走哪条路。

    【讨论】:

    • 您能说说一些优点和缺点吗?可能吗?
    • 性能优势主要是由于与符号表的交互较少;即没有明显的分配(尽管仍然可以在库方法中进行分配)。缺点将是由于使用.map() 而不是for 循环,并且需要减少和过滤由promise 传递的数据。总的来说,我猜缺点会占主导地位 - 性能会更差。
    • 也就是说,除非您的“结果”和“用户”拥有数千名成员,否则性能并不是真正的问题。最多只有数百个,您真的不会注意到差异。因此,对于小批量,我会接受(可能)较差的性能并享受代码的紧凑性。
    【解决方案3】:

    你需要改变这个

    then(function() {
                return Array.prototype.slice.apply(arguments).reduce(function(p, c) { // reduce an array of arrays to a single array
                    return p.concat(c);
                }).filter(function(value, idx, self) { // filter out duplicates
                    return self.indexOf(value22) === idx;
                });
    

    then(function() {
                return Array.prototype.slice.apply(arguments).reduce(function(p, c) { // reduce an array of arrays to a single array
                    return p.concat(c);
                }).filter(function(value, idx, self) { // filter out duplicates
                    return self.indexOf(value2) === idx;
                });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-23
      • 2022-01-04
      • 1970-01-01
      相关资源
      最近更新 更多