2

我想知道我应该采取什么途径使这段代码“按预期”工作。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;
    });
}

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

4

4 回答 4

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
});
于 2012-06-06T06:58:27.507 回答
3

...这是一种不好的做法。构造函数应该返回其类的实例,仅此而已。否则会弄乱新的运算符和继承。

此外,构造函数应该只创建和初始化一个新实例。它应该设置数据结构和所有特定于实例的属性,但不执行任何任务。如果可能的话,它应该是一个没有副作用的纯函数,并具有所有的好处。

参考:让构造函数返回 Promise 是不好的做法吗?

于 2015-04-25T00:11:31.643 回答
3

您可能想要使用$.ajax而不是$.getwith option async: false。但是,这将锁定所有其他 javascript 的执行。如果例如服务器因任何原因不响应,这可能是一个问题。

因此,这是一个不好的做法。使用回调,例如

function Song(songId, callback) {
    var self = this;
    $.getJSON('http://gdata.youtube.com/feeds/api/videos/' + songId + '?v=2&alt=json-in-script&callback=?', function (data) {
        self.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); });
        self.songId = songId;
        self.url = "http://youtu.be/" + songId;
        self.name = data.entry.title.$t;
        callback();
    });
}

var song = new Song(songId, function() {
    // The other code goes here.
});
于 2012-06-06T06:42:00.290 回答
0

同步调用可能会导致浏览器停止响应,并且某些浏览器可能会强行杀死您的脚本。

Jquery 在向 URI 发出请求时有一个选项

asyncBoolean 默认值:true

默认情况下,所有请求都是异步发送的(即默认设置为true)。如果您需要同步请求,请将此选项设置为 false。跨域请求和 dataType: "jsonp" 请求不支持同步操作。请注意,同步请求可能会暂时锁定浏览器,从而在请求处于活动状态时禁用任何操作。从 jQuery 1.8 开始,不推荐使用 async: false 。

http://api.jquery.com/jQuery.ajax/

希望这会有所帮助

问候。

于 2012-06-06T06:41:22.610 回答