如何在javascript中取消异步进程?
我有一个单窗口javascript应用程序。我有一个仪表板,通过在后台通过多个get请求加载来显示某些图像 当不是所有get请求都按时完成并且站点的上下文发生变化时,就会出现问题,因为我想清除仪表板。但是,如果get请求尚未完成,它们将用错误的图像填充仪表板 我正在想办法中止那些get请求。有人能告诉我正确的方向吗如何在javascript中取消异步进程?,javascript,jquery,asynchronous,Javascript,Jquery,Asynchronous,我有一个单窗口javascript应用程序。我有一个仪表板,通过在后台通过多个get请求加载来显示某些图像 当不是所有get请求都按时完成并且站点的上下文发生变化时,就会出现问题,因为我想清除仪表板。但是,如果get请求尚未完成,它们将用错误的图像填充仪表板 我正在想办法中止那些get请求。有人能告诉我正确的方向吗 var Dashboard = { showAllAssets: function(){ var self = this; this.rese
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();
}
}
正如注释所指出的,一种可能的解决方案是存储当前上下文,并在get请求的success方法中对其进行比较 到目前为止,我已经更改了代码,现在我将在管理器中存储当前事件,并将事件传递给
$.get
-方法
这有一个缺点,即get请求仍在处理中,如果要处理的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);
})
}
}
我创建了一个不同的解决方案,将请求存储在一个数组中,并在上下文更改时中止它们:
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;
}
});
},
虽然您无法停止已发送的请求,但仍然可以解决您的问题 我的解决方案是生成一个简单的ID,例如一组随机数字,并将其存储在仪表板中的某个位置,然后将其与请求一起发送,并将其与图像一起发送回 如果生成一个新的上下文,它将有一个新的ID
如果图像返回时的ID与当前上下文中的ID不同,则将其丢弃。可能不尝试取消请求,但在完成后,请在加载图像之前检查上下文是否相同。@ElliotBonneville这是一种有效的解决方法。如何存储当前上下文?我不太确定应该如何设置并比较get请求的success方法中的状态。我不太理解代码某些部分背后的原因(获取更多资产的setTimeout?),但如果您将所有这些请求包装在$.when()中,并一次性处理它们,再添加一个promise对象是很容易的,您可以拒绝该对象,从而有效地中止正在处理的任何一个对象,而不实际中止请求(避免控制台中显示错误),但一次触发的请求过多应该不是问题(除非您一次处理数百个请求,否则我想……在这种情况下,您应该重新考虑如何减少请求数量)。setTimeout使停止这些请求变得特别困难,因为您不仅必须中止现有请求,而且还必须逐个清除所有尚未完成的超时。当解决方案看起来有点过于复杂时,只测试上下文可能更容易(我没有任何建议,因为我不确定您的案例中的具体情况。)