卡在延迟 jQuery
Stuck on deferreds with jQuery
我卡住了。这毫无意义。
下面这行代码调用 loadJSONfile,然后在 getJSON 解析时设置对 dataLoaded 的调用。
$.when(loadJSONfile(pathToLoad + "/" + fileToLoad,provIdx)).done(dataLoaded);
这是 loadJSON 文件:
function loadJSONfile(pathToFile,idx1,idx2,num2,idx3,num3,dir) {
var deferred = $.Deferred();
//var IDX = idx;
/* code to load the stuff goes here */
$.getJSON(pathToFile).done(function(data) {
deferred.resolve(data,idx1,idx2,num2,idx3,num3,dir);
}).fail(function() { console.log('FAILED') });
return deferred.promise();
}
以下代码行调用 loadMapData,并在 loadMapData 解析时设置对 mapDataLoaded 的调用:
$.when(loadMapData(provinceEntry,regionIdx)).done(mapDataLoaded);
这是加载地图数据:
function loadMapData(provinceEntry,regionIdx) {
var deferred = $.Deferred();
var regionCode = provinceEntry.regions[regionIdx];
$.getJSON('data/topojson' + String(provinceEntry.Number) + String(regionCode) + '.topojson').done(function(topoData) {
deferred.resolve(topoData,provinceEntry,regionIdx);
})
}
但是没用。代码立即解决 deferred,这显然会导致 mapDataLoaded 失败。
为什么一个工作正常而另一个工作不工作?
loadMapData()
没有 returning 任何东西。它必须 return 对 $.when()
的承诺才能像您在 loadJSONfile()
中所做的那样完成它的工作。
但是,我必须说,您正在使用一些反模式来实现承诺(在不需要时创建新的承诺)。
这是一个没有反模式和 return 承诺的固定 loadMapData()
:
function loadMapData(provinceEntry,regionIdx) {
var regionCode = provinceEntry.regions[regionIdx];
return $.getJSON('data/topojson' + provinceEntry.Number + regionCode + '.topojson');
}
loadMapData(provinceEntry,regionIdx).then(function(topoData) {
// you can refer to topoData, provinceEntry and regionIdx here
mapDataLoaded(topoData, provinceEntry,regionIdx);
}, function(err) {
// error handling here
});
避免反模式的关键是避免在 $.getJSON()
已经 return 时创建新的承诺,因此您只需使用已经 returned 的承诺.
还有,关于 $.when()
的一句话。首先,你必须传递一个或多个承诺。它没有神奇的力量知道你传递给它的某些异步函数何时实际完成。它只知道如何使用承诺。其次,除非您试图协调多个承诺,否则使用 $.when()
的理由为零。如果你只有一个承诺,你可以只在承诺本身上使用 .then()
(就像我在上面的 loadMapData()
上所做的那样 - 没有必要将它包装在 $.when()
.
我卡住了。这毫无意义。
下面这行代码调用 loadJSONfile,然后在 getJSON 解析时设置对 dataLoaded 的调用。
$.when(loadJSONfile(pathToLoad + "/" + fileToLoad,provIdx)).done(dataLoaded);
这是 loadJSON 文件:
function loadJSONfile(pathToFile,idx1,idx2,num2,idx3,num3,dir) {
var deferred = $.Deferred();
//var IDX = idx;
/* code to load the stuff goes here */
$.getJSON(pathToFile).done(function(data) {
deferred.resolve(data,idx1,idx2,num2,idx3,num3,dir);
}).fail(function() { console.log('FAILED') });
return deferred.promise();
}
以下代码行调用 loadMapData,并在 loadMapData 解析时设置对 mapDataLoaded 的调用:
$.when(loadMapData(provinceEntry,regionIdx)).done(mapDataLoaded);
这是加载地图数据:
function loadMapData(provinceEntry,regionIdx) {
var deferred = $.Deferred();
var regionCode = provinceEntry.regions[regionIdx];
$.getJSON('data/topojson' + String(provinceEntry.Number) + String(regionCode) + '.topojson').done(function(topoData) {
deferred.resolve(topoData,provinceEntry,regionIdx);
})
}
但是没用。代码立即解决 deferred,这显然会导致 mapDataLoaded 失败。
为什么一个工作正常而另一个工作不工作?
loadMapData()
没有 returning 任何东西。它必须 return 对 $.when()
的承诺才能像您在 loadJSONfile()
中所做的那样完成它的工作。
但是,我必须说,您正在使用一些反模式来实现承诺(在不需要时创建新的承诺)。
这是一个没有反模式和 return 承诺的固定 loadMapData()
:
function loadMapData(provinceEntry,regionIdx) {
var regionCode = provinceEntry.regions[regionIdx];
return $.getJSON('data/topojson' + provinceEntry.Number + regionCode + '.topojson');
}
loadMapData(provinceEntry,regionIdx).then(function(topoData) {
// you can refer to topoData, provinceEntry and regionIdx here
mapDataLoaded(topoData, provinceEntry,regionIdx);
}, function(err) {
// error handling here
});
避免反模式的关键是避免在 $.getJSON()
已经 return 时创建新的承诺,因此您只需使用已经 returned 的承诺.
还有,关于 $.when()
的一句话。首先,你必须传递一个或多个承诺。它没有神奇的力量知道你传递给它的某些异步函数何时实际完成。它只知道如何使用承诺。其次,除非您试图协调多个承诺,否则使用 $.when()
的理由为零。如果你只有一个承诺,你可以只在承诺本身上使用 .then()
(就像我在上面的 loadMapData()
上所做的那样 - 没有必要将它包装在 $.when()
.