3

我正在构建一个插件,它以 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 会有所帮助,但可惜:我需要在没有任何外部库的情况下编写它。:(

对其他代码气味的评论也会很好!

4

3 回答 3

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();
于 2013-03-20T01:31:35.170 回答
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(其中一些在运行时不需要额外的库即可工作)。

于 2013-03-20T03:36:02.043 回答
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,或者这是否明智?

于 2013-03-20T16:49:21.197 回答