Node.js代码仅在sequelize

时间:2017-03-02 04:44:41

标签: javascript node.js sequelize.js

当在我的服务器端代码的顶部时,这很好,产生的结果是正确的:

var data_playlists = {};

models.Playlist.findAll({
attributes: ['id', 'name']
 }).then(function (playlists){
  data_playlists['playlists'] = playlists.map(function(playlist){
  return playlist.get({plain: true})
});
addsongs(data_playlists, 1);
addsongs(data_playlists, 2);
addsongs(data_playlists, 3);

});

但是如果它在我的一种Express方法中,它就不能正常运行;特别是,addongs方法不能正常工作。

function addsongs(playlist_object, id_entered){
 var arraysongs = [];

 models.Playlist.findOne({
      attributes: ['id'],
      where: {
          id: id_entered
      }
  })
  .then(function(playlist) {
      playlist.getSongs().then(function (thesongs){
        for(var k = 0; k < thesongs.length ; k++){
          arraysongs.push(thesongs[k].Songs_Playlists.SongId);
        }
        playlist_object.playlists[(id_entered - 1)]['songs'] = arraysongs;
      });
  });
}

我不能为我的生活弄明白为什么当代码的顶部代码位于顶部时它起作用,但在我的app.get()调用内部不起作用。

1 个答案:

答案 0 :(得分:1)

从您的代码中我已经指出,您希望将播放列表(idname)与其歌曲(id)一起返回。首先,您的代码无法正常工作,因为addsongs(data_playlists, id)的调用在data_playlists之前运行,并且上面的代码填充了数据。此外,addsongs函数执行返回Promises的异步操作,因此逐个调用它们将不会给出预期的结果。我想你可以完全不同地做到这一点。

我建议您使用include对象的options属性,该属性可以传递给findAll()方法。 include说明您还希望从当前查询返回哪种关联模型。在这种情况下,您希望将播放列表与其歌曲一起返回(根据您的代码,M:M关系),因此您需要在查询中包含Song模型。

function getPlaylistsWithSongs() {
    return models.Playlist.findAll({
        attributes: ['id', 'name'],
        include: [
            {
                model: models.Song,
                as: 'Songs', // depends on how you have declare the association between songs and playlists
                attributes: ['id'],
                through: { attributes: [] } // prevents returning fields from join table
            }
        ]
    }).then((playlistsWithSongs) => {
        return playlistsWithSongs;
    });
}

getPlaylistsWithSongs结果的示例结果将是(在将其翻译为JSON之后,例如playlistsWithSongs.toJSON()

[
    {
        id: 1,
        name: 'playlist #1',
        Songs: [
            { id: 1 },
            { id: 2 }
        ]
    }
]

以上代码会返回所有playlists(他们的idname)及其songs(只有他们的id)。现在在你的路线解析器中你可以简单地调用上面的函数来返回结果

app.get('/api/playlists', function (request, response) {
    response.setHeader("Content-Type", "application/json; charset=UTF-8");
    getPlaylistsWithSongs().then(function(playlistsWithSongs){
        response.status(200).send(JSON.stringify(playlistsWithSongs));
    });
});

修改

为了简单地返回ID数组而不是id(songs)的对象数组,您需要映射结果。在这种情况下,没有简单的续集方式来返回ID数组。

}).then((playlistWithSongs) => {
    let jsonPlaylists = playlistsWithSongs.map((singlePlaylist) => {
        // return JSON representation of each playlist record
        return singlePlaylist.toJSON();
    });

    jsonPlaylists.forEach((playlist) => {
        // at every playlist record we map Songs to array of primitive numbers representing it's IDs
        playlist.songs = playlist.Songs.map((song) => {
            return song.id;
        });

        // when we finish we can delete the Songs property because now we have songs instead
        delete playlist.Songs;
    });

    console.log(jsonPlaylists);
    // example output: [{ id: 1, name: 'playlist #1', songs: [1, 2, 3] }]
    return jsonPlaylists;
});