javascript - Node.js 代码仅在带有 Sequelize 的文件顶部工作

标签 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 方法之一内时,它无法正常运行;特别是,addsongs 方法无法正常工作。

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() 调用中却不起作用。

最佳答案

根据您的代码,我发现您想要返回播放列表(idname)及其歌曲(id)。首先,您的代码将无法工作,因为 addsongs(data_playlists, id) 的调用是在 data_playlists 通过上面的代码填充数据之前运行的。此外,addsongs 函数执行异步操作并返回 Promises,因此逐一调用它们不会给出预期结果。我想你可以完全不同地做到这一点。

我建议您使用可以传递给 findAll() 方法的 options 对象的 include 属性。 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 }
        ]
    }
]

以上代码返回所有播放列表(其idname)及其歌曲(仅其 >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),您需要映射结果。在这种情况下,没有简单的 Sequelize 方法可以返回 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;
});

关于javascript - Node.js 代码仅在带有 Sequelize 的文件顶部工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42547052/

相关文章:

sql - 在 Sequelize 中使每个用户 ID 的字段唯一?

javascript - 在 HTML 表行 DOM 元素中查找行索引

node.js - 如何使用 Node.js 代码获取所有 mongoDB 集合名称?

mysql - express js - 使用 sequelize 时找不到 GET 请求 404

javascript - 使用appendFileSync时是否需要指定目录?

javascript - 从 https 网站调用 http api

sql-server - 如何使用 SequelizeJS 从表中返回非常插入的 ID?

javascript - jquery选择器按宽度

javascript - AutoHotKey Com 对象获取选择列表

javascript - 如何在一个页面上关闭多个模态框