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

Constructor that needs data from asynchronous API call?

本文关键字:调用 数据 构造函数 API 异步      更新时间:2023-09-26

我想知道我应该采取什么途径来使这段代码"按预期"工作。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 相关的信息带到其范围之外。

与大多数异步操作一样,在这种情况下我会使用 Deferred; 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
});
您可能

希望使用$.ajax而不是带有选项 async: false$.get。但是,这将锁定所有其他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.
});

。这是一种不好的做法。构造函数应返回 它的类,没有别的。这会搞砸新的运营商和 否则继承。

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

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

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

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

异步布尔默认值:真

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

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

希望这会有所帮助

问候。