我正在构建一个插件,用于获取JSON中的一堆图像的信息,然后在一些对话框中显示它们以供选择。不幸的是,我的第一个直觉很明显会导致竞争条件:
var ImageDialog = function () {};
ImageDialog.prototype.items = [];
ImageDialog.prototype.fetch_images() {
var parse_images = function(data) {
// Magically parse these suckers.
data = awesome_function(data);
this.items = data;
};
magicalxhrclass.xhr.send({"url": 'someurl', "success": parse_images, "success_scope": this});
}
ImageDialog.prototype.render = function () {
this.fetch_images();
// XHR may or may not have finished yet...
this.display_images();
this.do_other_stuff();
};
var monkey = new ImageDialog();
monkey.render();
我认为可以通过更改parse_images
回调以包含其余的渲染步骤来解决这个问题。但是,这看起来不太合适。为什么fetch_images
方法会调用一堆关于显示图像的东西?
那么:我该怎么办?
我非常肯定deferreds会有所帮助,但是唉:我需要在没有任何外部库的情况下编写它。 :(
对其他代码气味的评论也会很好!
答案 0 :(得分:2)
这个怎么样?
var ImageDialog = function () {
this.items = []; // just in case you need it before the images are fetched
};
ImageDialog.prototype.fetch_images(callback) {
var that = this;
function parse_images (data) {
// Magically parse these suckers.
data = awesome_function(data);
that.items = data;
callback.apply(that);
};
magicalxhrclass.xhr.send({"url": 'someurl', "success": parse_images, "success_scope": this});
}
ImageDialog.prototype.render = function () {
this.fetch_images(function(){
this.display_images();
this.do_other_stuff();
});
};
var monkey = new ImageDialog();
monkey.render();
答案 1 :(得分:2)
一般来说,你可以使用的基本思想是当常规程序使用return语句时(意思是“我的函数现在完成你的工作!”)异步延续传递程序将使用ballcabk函数得到明确称为
function fetch_images(callback){
magicalXHR({
success: function(data){
parse_images(data);
callback(whatever);
}
}
}
或者,如果parse_images本身是异步函数:
parse_images(data, callback)
现在当你调用fetch_images后代码进入回调而不是假设fetch_images将在返回时完成
fetch_images(function(
display_images()
})
通过使用回调,您可以很好地模拟传统程序可以做什么(实际上它是另一种形式之间的相当机械的转换)。你现在遇到的唯一问题是错误处理变得棘手,像循环这样的语言功能不能很好地处理异步回调,并且回调倾向于嵌入到回调地狱中。如果回调开始变得过于复杂,我会调查使用其中一种Javascript方言,这些方言编译为延续传递式Javascrit(其中一些工作在运行时不需要额外的库)。
答案 2 :(得分:0)
这是一个关于该怎么做的想法。
ImageDialog.prototype.fetch_images() {
var parse_images = function(data) {
// Magically parse these suckers.
data = awesome_function(data);
this.items = data;
fetch_images.caller() // Unfortunately, this is nonstandard/not in the spec. :(
};
magicalxhrclass.xhr.send({"url": 'someurl', "success": parse_images, "success_scope": this});
}
ImageDialog.prototype.render = function () {
if (this.items === []) {
this.fetch_images()
return;
} else {
this.display_images();
this.do_other_stuff();
};
};
这样我就不会将一些实现细节传递给fetch_images,而是进行缓存,以便启动。我是否仍在努力逃避CPS,或者这是否明智?