【问题标题】:return q.all() not waiting to resolve unless wrapped in deferred.resolvereturn q.all() 不等待解决,除非包装在 deferred.resolve
【发布时间】:2018-03-17 12:43:20
【问题描述】:

所以我今天意识到我一直在通过使用递归和嵌套 promise 严重地迭代 promise,并且想学习如何正确使用 Q.all()。我正在尝试遍历一系列异步函数并等待它们全部解决后再继续。在当前的实现中,Q.all 会立即返回,而无需等待 Promise 解决。这是我的迭代函数代码

var updateNewReleasePlaylists = function () {
    var self = this;
    var promises = [];
    var deferred = Q.defer();

    // query for all users who have new releases
    User.find({
            $and: [{
                    'new_releases': {
                        $exists: true,
                        $ne: []
                    }
                },
                {
                    'refresh_token': {
                        $exists: true
                    }
                }
            ]
        }, 'new_releases',
        function (err, users) {
            if (err) {
                throw new Error(err);
            }
            for (var i = 0; i < users.length; i++) {
                console.log('when?')
                promises.push(updatePlaylist(users[i]));
            }
        });
return Q.all(promises);

}

这里是它调用的异步函数:

function updatePlaylist(user) {
    var deferred = Q.defer();
    User.findOne({'_id': user._id}, function(err, user) {
        if (err) {
            deferred.reject(err);
        }
        console.log(user);
        deferred.resolve();
    })
    return deferred.promise;
}

如果我像这样更改实现,它完全可以正常工作:

var updateNewReleasePlaylists = function () {
    var self = this;
    var promises = [];
    var deferred = Q.defer();

    // query for all users who have new releases
    User.find({
            $and: [{
                    'new_releases': {
                        $exists: true,
                        $ne: []
                    }
                },
                {
                    'refresh_token': {
                        $exists: true
                    }
                }
            ]
        }, 'new_releases',
        function (err, users) {
            if (err) {
                throw new Error(err);
            }
            for (var i = 0; i < users.length; i++) {
                console.log('when?')
                promises.push(updatePlaylist(users[i]));
            }
            deferred.resolve(Q.all(promises)); // DIFFERENT
        });
        return deferred.promise; // DIFFERENT
}

据我所知,这是一种不正确的实现方式,但我想在第一时间就做好。如果有任何帮助,我在这里调用updateNewReleasePlaylists 函数进行测试。

it('updateNewReleasePlaylists should properly resolve after all users playlists have been updated', function (done) {
        this.timeout(60000);
        testHelper.stageSpotifyUser(20)
            .then(testHelper.stageSpotifyUser(20))
            .then(testHelper.stageSpotifyUser(20))
            .then(function () {
                playlist.updateNewReleasePlaylists()
                    .then(function (promises) {
                        console.log(promises.length);
                        console.log('should be after');
                        done();
                    })
            })
    })

提前感谢您的帮助。

【问题讨论】:

  • 您正在异步(在find 回调中!)推送到promises 数组,然后在Q.all 中立即使用它。当然,它在那里是空的,并立即实现。您应该正确地承诺User.find,并在then 回调中使用数组和Q.all only

标签: javascript node.js promise q


【解决方案1】:

如果 promises 数组是空的,那么得到你的回报似乎是正确的,因为没有什么可以等待的。当 find() 完成时,由于它的异步特性,promises 数组仍然是空的,因为函数 (err, users) 还没有被调用。

所以,如果我认为 find() 是异步的,你应该返回整个 User.find() 或 promise-wrap 如果需要并返回它。

【讨论】:

  • 是的 User.find 是异步的。所以在这个特定的用例中,可以将 Q.all 包装在 deferred.resolve() 中吗?我在网上看到的许多示例都没有这样做。
  • 我认为承诺包装没有任何问题。有这样做的库。如果我提供帮助,请将我的答案标记为已接受。雪儿
猜你喜欢
  • 2018-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-23
  • 2021-08-02
  • 2021-05-19
相关资源
最近更新 更多