Q 承诺和 mongo db q.all

Q promises and mongo db q.all

我正在调用 mongodb 数据库 - 提取数据...读取它,然后根据该数据发出进一步的请求。收到所有数据后,我想处理它。

我一直在使用 Q.promises 库,但不知道我在做什么。我以为 q.all 只有在一切都完成后才会触发?但是,我的 processPlaylist 函数运行了两次。我评论了下面的代码:

谢谢, 罗布

var PlaylistCollection = require('./models/playlist');
var AssetCollection = require('./models/asset');
var screenID = '############';
var playerData = [];
// array continaing playlistys which have been synced
var alreadySynced = [];

// Process our playlist once downloaded
    var processPlaylist = function (playerData) {
    console.log('----Processing Playerlist-----')
    console.log(playerData);
    // DO STUFF
}


// Get playlist by id. Return playlist Data
var getSubLists = function (id) {
    return PlaylistCollection.findById(id);
}



// Get sub-playlist function

function getSubListRecursive(id) {

return getSubLists(id).then(function (playlist) {

    // store all our returned playlist data into a playlist array
    playerData.push(playlist)

    // an Array to keep tabs on what we've already pulled down
    alreadySynced.push(playlist.id)

    // get all our playlist.resources, and only return those which are unique
    var playlistResources = _.uniq(playlist.resources, 'rid');
    //  console.log('Playlist Resources: ', playlistResources)
    //  console.log(alreadySynced);
    var sublists = _.pluck(_.filter(playlistResources, { 'type': 'playlist' }), 'rid');
    // remove playlists which have already been synced. We don't want to pull them down twice
    sublists = _.difference(sublists, alreadySynced);
    //  console.log('sublists: ', sublists)

    // Get the next playlist and so on...
    var dbops = sublists.map(function (sublist) {
        // console.log(sublist)
        return getSubListRecursive(sublist)
    });

    q.all(dbops).then(function () {
        console.log('All Done - so process the playlist')
        return processPlaylist(playerData);
    });

})

}


// Trigger the whole process..... grab our first playlist / ScreenID
getSubListRecursive(screenID);

我得到以下输出:

    ----Processing Playerlist-----
[ { _id: 554d1df16ce4c438f8e2225b,
    title: 'list 1',
    __v: 29,
    daily: true,
    endTime: '',
    startTime: '',
    resources:
     [ { rid: '55650cebef204ab70302a4d9',
         title: 'list 4',
         type: 'playlist' },
       { rid: '554d1df16ce4c438f8e2225b',
         title: 'list 1',
         type: 'playlist' } ] },
  { _id: 55650cebef204ab70302a4d9,
    title: 'list 4',
    __v: 1,
    daily: false,
    endTime: '',
    startTime: '',
    resources:
     [ { rid: '55650647ef204ab70302a4d8',
         title: 'list 3',
         type: 'playlist' } ] } ]
All Done - so process the playlist
----Processing Playerlist-----
[ { _id: 554d1df16ce4c438f8e2225b,
    title: 'list 1',
    __v: 29,
    daily: true,
    endTime: '',
    startTime: '',
    resources:
     [ { rid: '55650cebef204ab70302a4d9',
         title: 'list 4',
         type: 'playlist' },
       { rid: '554d1df16ce4c438f8e2225b',
         title: 'list 1',
         type: 'playlist' } ] },
  { _id: 55650cebef204ab70302a4d9,
    title: 'list 4',
    __v: 1,
    daily: false,
    endTime: '',
    startTime: '',
    resources:
     [ { rid: '55650647ef204ab70302a4d8',
         title: 'list 3',
         type: 'playlist' } ] },
  { _id: 55650647ef204ab70302a4d8,
    title: 'list 3',
    __v: 5,
    daily: false,
    endTime: '',
    startTime: '',
    resources:
     [ { rid: '55650637ef204ab70302a4d7',
         title: 'list 2',
         type: 'playlist' },
       { rid: '554d1df16ce4c438f8e2225b',
         title: 'list 1',
         type: 'playlist' },
       { rid: '55650cebef204ab70302a4d9',
         title: 'list 4',
         type: 'playlist' } ] } ]    

编辑

我写的东西有很多错误。我和我的一个朋友讨论过这个问题——他指出 getSubListRecursive 被递归调用了好几次所以 q.all 语句被执行了好几次...

所以我重构了...

// Get sub-playlist function

function getSubListRecursive(id) {
    console.log(id)
    return getSubLists(id).then(function (playlist) {
        if (playlist) {
            // store all our returned playlist data into a playlist array
            playerData.push(playlist)
            // an Array to keep tabs on what we've already pulled down
            alreadySynced.push(playlist.id)
            // get all our playlist.resources, and only return those which are unique
            var playlistResources = _.uniq(playlist.resources, 'rid');
            //  console.log('Playlist Resources: ', playlistResources)
            //  console.log(alreadySynced);
            var sublists = _.pluck(_.filter(playlistResources, { 'type': 'playlist' }), 'rid');
            // remove playlists which have already been synced. We don't want to pull them down twice
            sublists = _.difference(sublists, alreadySynced);
            //  console.log('sublists: ', sublists)
            return sublists.map(function (sublist) {
                // console.log(sublist)
                if (sublists.length > 0) {
                    return getSubListRecursive(sublist)
                } else {
                    return processPlaylist(playerData);
                }
            });
        } else {
            return processPlaylist(playerData);
        }
    });
}

这行得通。我基本上是使用 promises 来控制这里的流程——这可能不是最好的方法?我不再使用 all 语句,最终得到填充了所有播放列表数据的数组——我可以在我的 processPlaylist 函数中对其进行操作。

但是,我没有将问题标记为已解决,因为我真的很想知道如何使用 Q.all(正确使用承诺)

谢谢, 罗布

我想您只是对整个过程何时完成感到困惑。您需要等到整个递归承诺链都已解决。我认为您可以使用原始代码,对调用 processPlaylist() 的位置稍作更改:

var PlaylistCollection = require('./models/playlist');
var AssetCollection = require('./models/asset');
var screenID = '############';
var playerData = [];
// array continaing playlistys which have been synced
var alreadySynced = [];

// Process our playlist once downloaded
var processPlaylist = function (playerData) {
    console.log('----Processing Playerlist-----')
    console.log(playerData);
    // DO STUFF
}


// Get playlist by id. Return playlist Data
var getSubLists = function (id) {
    return PlaylistCollection.findById(id);
}

// Get sub-playlist function
function getSubListRecursive(id) {
    return getSubLists(id).then(function (playlist) {
        // store all our returned playlist data into a playlist array
        playerData.push(playlist)

        // an Array to keep tabs on what we've already pulled down
        alreadySynced.push(playlist.id)

        // get all our playlist.resources, and only return those which are unique
        var playlistResources = _.uniq(playlist.resources, 'rid');
        //  console.log('Playlist Resources: ', playlistResources)
        //  console.log(alreadySynced);
        var sublists = _.pluck(_.filter(playlistResources, { 'type': 'playlist' }), 'rid');
        // remove playlists which have already been synced. We don't want to pull them down twice
        sublists = _.difference(sublists, alreadySynced);
        //  console.log('sublists: ', sublists)

        // Get the next playlist and so on...
        var dbops = sublists.map(function (sublist) {
            // console.log(sublist)
            return getSubListRecursive(sublist)
        });

        return q.all(dbops);
    });
}

// Trigger the whole process..... grab our first playlist / ScreenID
getSubListRecursive(screenID).then(function() {
    console.log('All Done - so process the playlist')
    return processPlaylist(playerData);
});