2012-06-06 33 views
2

我不知道我应该采取什么样的途径来使这个代码的工作“的预期。” API调用是异步的 - 所以构造函数在数据加载之前返回。需要异步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; 
    }); 
} 

是否有可能强制构造函数不提前返回?理想情况下,我不会要的参数任意量传递到宋构造和带来的只是宋它的范围之外的相关信息..

回答

3

您可能想要使用$.ajax而不是$.get并使用选项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. 
}); 
+0

我认为这是我想要的。让我试试看,一秒钟。 –

+1

'getJSON'回调中的'this'不会引用'Song'实例。 – lanzz

+0

@lanzz哦,是的。我刚刚复制了代码。让我编辑它。 – freakish

0

同步调用可能导致浏览器停止响应,一些浏览器可能会杀了你的脚本有力地。

Jquery的有一个选项,同时使一个URI

asyncBoolean默认的请求:真

缺省情况下,所有的请求是非同步地发送(即,这是通过默认设置为 真)。如果您需要同步请求,请将此选项设置为 false。跨域请求和dataType:“jsonp”请求不支持 同步操作。请注意,同步请求可能会暂时 锁定浏览器,禁用任何行动,同时请求 处于活动状态。从jQuery 1.8开始,不赞成使用async:false。

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

希望这将有助于

问候。

+0

嗯,我应该担心使用过时的参数? –

+0

我希望你不使用jquery 1.8,因为它现在还不稳定。但您可以安全地在1.7.x上使用它。 –

7

与大多数异步操作,我会使用一个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 
}); 
+0

比回调方案更好。 –

+1

很老的线程我知道,但是然后返回承诺,为什么不把它存储在'this.promise = def.promise();'然后在异步回调'def.resolve(this)'?这样构造函数返回对象,并且回调可以按照这种方式链接:'var song = new Song(songId); song.promise.done(function(){doWhatever()})' – undefinederror

+0

@undefinederror是一个很好的观点。单例构造函数不应该返回任何东西,除了它自己的实例 –

3

...这是一个不好的做法。构造函数应该返回其类的实例,没有别的。否则它会弄乱新的运营商和继承。

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

编号:Is it bad practice to have a constructor function return a Promise?