Q promises和mongo db q.all

时间:2015-05-27 10:26:43

标签: node.js mongodb q

我正在调用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(正确使用承诺)来做到这一点

谢谢, 罗布

1 个答案:

答案 0 :(得分:0)

我认为你对整个过程何时完成感到困惑。您需要等到整个递归承诺链已解决。我认为您可以使用原始代码稍微更改一下调用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);
});