如何在javascript中取消异步进程?

时间:2014-01-30 18:10:39

标签: javascript jquery asynchronous

我有一个单窗口的JavaScript应用程序。我有一个仪表板,通过在后台通过多个获取请求加载来显示某些图像。

当并非所有获取请求都按时完成并且网站的上下文发生变化时会出现问题,因为我想清除仪表板。然而,如果获取请求还没有完成,他们将使用错误的图像填充仪表板。

我试图想办法中止那些获取请求。有人可以指导我朝正确的方向发展吗?

var Dashboard = {
    showAllAssets: function(){
        var self = this;
        this.resetDashboard();

        $.get(this.urlForAllAssets, function(json){
           self.loadAssets(json);
        });

    },
    showAssetsForCategory: function(categoryId) {
        ...

    },
    getHtmlForAsset: function(id) {
        var self = this;
        $.get(this.urlForDashboardThumb + "/" + id.toString(), function(assetHtml){
            var $asset = $(assetHtml);
            self.insertAssetThumbIntoDom($asset);
            // this gets inserted even when context changed, how can I prevent that?
            var thumb = Object.create(Thumbnail);
            thumb.init($asset);
        }, 'html')
    },
    insertAssetThumbIntoDom: function($asset) {
        $asset.appendTo(this.$el);
    },
    resetDashboard: function() {
        this.$el.html("");
    },
    loadAssets: function(idList) {
        var self = this;
        var time = 200;

        // These get requests will pile up in the background

        $.each(idList, function(){
            var asset = this;
            setTimeout(function(){
                self.getHtmlForAsset(asset.id);
            }, time);
            time += 200;
        });
    },
    bind: function() {
        $document.on('loadAssets', function(event, idList) {
            self.loadAssets(idList);
        });

        $document.on('switched_to_category', function(event, categoryId) {
            self.showAssetsForCategory(categoryId);
        });

        $document.on('show_all_assets', function(){
            self.showAllAssets();
        })
    },
    init: function($el) {
        this.$el = $el;
        this.resetDashboard();
        this.bind();
    }
}

3 个答案:

答案 0 :(得分:1)

虽然您无法停止已发送的请求,但仍可以解决问题。

我的解决方案是生成一个简单的ID,例如一组随机数字,然后存储在仪表板中的某个位置,并将其与请求一起发送,然后将其与图像一起发回。

如果生成了新的上下文,它将具有新的ID。

如果图像的ID不同于当前上下文中的ID,则丢弃它。

答案 1 :(得分:0)

正如评论所指出的,一种可能的解决方案是存储当前上下文,并在get请求的success方法中对其进行比较。

我已经更改了我的代码,因为现在我将把当前内容存储在管理器中,并将事件传递给$.get - 方法。

这有一个缺点,即仍然处理get请求,并且新上下文的加载需要更长时间,因为如果有太多要处理的请求将在稍后处理。我也不喜欢传递这个事件。

var Dashboard = {
    currentLoadEvent: null,
    loadAssets: function(idList, event) {
        var self = this;

        $.each(idList, function(){
            var asset = this;
            self.getHtmlForAsset(asset.id, event);
        });
    },
    getHtmlForAsset: function(id, event) {
        var self = this;
        $.get(this.urlForDashboardThumb + "/" + id.toString(), function(assetHtml){
            if (event === self.currentLoadEvent) {
                console.log('same event continuing');
                var $asset = $(assetHtml);
                self.insertAssetThumbIntoDom($asset);
                var thumb = Object.create(Thumbnail);
                thumb.init($asset);
            } else {
                console.log('context changed');
            }
        }, 'html')
    },
    bind: function() {
        var self = this;

        $document.on('loadAssets', function(event, idList) {
            self.currentLoadEvent = event;
            self.loadAssets(idList, event);
        });

        $document.on('switched_to_category', function(event, categoryId) {
            self.currentLoadEvent = event;
            self.showAssetsForCategory(categoryId, event);
        });

        $document.on('show_all_assets', function(event){
            self.currentLoadEvent = event;
            self.showAllAssets(event);
        })
    }
}

答案 2 :(得分:0)

我通过将请求存储在数组中并在上下文更改时中止它来创建了一个不同的解决方案:

    loadAssets: function(idList, event) {
        var self = this;
        var requests = [];

        $.each(idList, function(){
            var asset = this;
            if (self.currentLoadEvent === event){
                var request = $.get(self.urlForDashboardThumb + "/" + asset.id.toString(), function(assetHtml){
                    if (event === self.currentLoadEvent) {
                        var $asset = $(assetHtml);
                        self.insertAssetThumbIntoDom($asset);
                        var thumb = Object.create(Thumbnail);
                        thumb.init($asset);
                        console.log('completed get request');
                    } else {
                        console.log('context changed');
                        $.each(requests, function(){
                            this.abort();
                            console.log('aborted request');
                        })
                    }
                }, 'html');
                requests.push(request);
            } else {
                return false;
            }
        });
    },