需要来自异步API调用的数据的构造函数?

Sea*_*son 2 javascript jquery constructor asynchronous callback

我想知道我应该采取什么样的方法来使这段代码按照预期的方式运行.API调用是异步的 - 因此构造函数在加载数据之前返回.

addSongById: function (songId) {
    var song = new Song(songId);
    console.log(song);
    this.addSong(song);

    if (this.songCount() == 1)
        this.play();

    UserInterface.refresh();
    SongGrid.reload();
},

function Song(songId) {
    $.getJSON('http://gdata.youtube.com/feeds/api/videos/' + songId + '?v=2&alt=json-in-script&callback=?', function (data) {
        this.id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); });
        this.songId = songId;
        this.url = "http://youtu.be/" + songId;
        this.name = data.entry.title.$t;
    });
}
Run Code Online (Sandbox Code Playgroud)

是否有可能强制构造函数不能过早返回?理想情况下,我不必将任意数量的参数传递给Song构造函数,并将仅与Song相关的信息带到其范围之外.

lan*_*nzz 7

和大多数异步操作一样,我Deferred在这种情况下使用a ; JS中的构造函数没有义务返回自己的实例:

function Song(songId) {
    var song = this;
    var def = new $.Deferred();
    $.getJSON('http://gdata.youtube.com/feeds/api/videos/' + songId + '?v=2&alt=json-in-script&callback=?', function (data) {
        song.id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); });
        song.songId = songId;
        song.url = "http://youtu.be/" + songId;
        song.name = data.entry.title.$t;
        def.resolve(song);
    });
    return def.promise();
}

var promise = new Song(songId);
promise.done(function(instance) {
    // you've got a Song instance
});
Run Code Online (Sandbox Code Playgroud)