在我的网页加载中,我必须检索三个JSON(对于loadJSON()
,请参阅 PS )
$(document).ready(function() {
loadJSON("JSON1.json",function(json){
json1 = json:
console.log("JSON1 loaded");
});
loadJSON("JSON2.json",function(json){
json2 = json:
console.log("JSON2 loaded");
});
loadJSON("JSON3.json",function(json){
json3 = json:
console.log("JSON3 loaded");
});
//doing stuff after all three have loaded (PSEUDO:)
waitTillFinished(doingStuff(json1, json2, json3));
});
然后我需要运行一个结合三个JSON(doingStuff
函数)的结果的函数,因此它必须等到所有三个JSON完成。
我虽然有一个功能可以进行主动等待并触发一个回调,例如doingStuff
。
我该怎么做?
我在这里寻找某种信号量模式。这通常是如何在JS中完成的?
已经尝试过:
jQuery构造:
$( document ).ready(function() {
$.when(
loadJSON("JSON1.json",function(json){
json1 = json;
console.log("JSON1 loaded");
}),
loadJSON("JSON2.json",function(json){
json2 = json;
console.log("JSON2 loaded");
}),
loadJSON("JSON3.json",function(json){
json3 = json;
console.log("JSON3 loaded");
})
).then(
doingStuff(json1, json2, json3);
);
});
这不等待完成的调用。这是完全理解的,因为loadJSON函数已经完成,只有回调还没有被解雇。
使用" status-semaphores"
var status1 = $.getJSON("JSON1.json"[..]); //shortend [..]
var status2 = $.getJSON("JSON2.json"[..]); //shortend [..]
var status3 = $.getJSON("JSON3.json"[..]); //shortend [..]
status1.complete(function(){
status2.complete(function(){
status3.complete(doingStuff(json1, json2, json3)
}
}
这确实有效,但不能扩展。对于两个电话,它会考虑这个解决方案,三个已经有气味。但是,当应用程序增长时,我希望能够获得更多的呼叫。
PS:
loadJSON()
函数是一个辅助函数,用于加载和记录请求内容:
function loadJSON(requestURL, callback){
var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open('GET', requestURL, true);
xobj.onreadystatechange = function(){
if (xobj.readyState == 4){
if(xobj.status == 200){
callback(JSON.parse(xobj.responseText));
} else {
console.error(xobj.statusText);
}
}
}
xobj.onerror = function(e){
console.error(xobj.statusText);
}
xobj.send();
}
答案 0 :(得分:3)
使用$.when
的代码可以使用,如果 loadJSON
返回一个承诺/延期,就像jQuery' getJSON
那样。所以:
$( document ).ready(function() {
$.when(
$.getJSON("JSON1.json"),
$.getJSON("JSON2.json"),
$.getJSON("JSON3.json")
).then(function(data1, data2, data3) { // Note naming, once they're parsed (which
doingStuff(data1, data2, data3); // getJSON does), they're not JSON anymore
});
});
或实际上,如果doingStuff
按照我们将调用传递给$.when
的顺序获取三个参数,则我们不需要包装函数:
$( document ).ready(function() {
$.when(
$.getJSON("JSON1.json"),
$.getJSON("JSON2.json"),
$.getJSON("JSON3.json")
).then(doingStuff);
});
注意我已使用then
代替done
。不同寻常的是,then
回调将针对每个结果使用离散参数进行调用(而普通then
仅使用一个参数调用其回调)。请注意,如果您改为使用done
,则会获得三个离散参数,但它们会数组,其中每个数组都包含数据,textStatus和jqXHR对象来自$.getJSON
电话。
或者我们可以使用Promise.all
(在任何主要的现代浏览器上):
$( document ).ready(function() {
Promise.all([
$.getJSON("JSON1.json"),
$.getJSON("JSON2.json"),
$.getJSON("JSON3.json")
]).then(function(results) {
doingStuff(results[0], results[1], results[2]);
});
});
注意我们将promises作为数组传递,然后返回一个数组。在ES2015 +中,我们可以在then
回调的参数列表中使用解构:
$( document ).ready(function() {
Promise.all([
$.getJSON("JSON1.json"),
$.getJSON("JSON2.json"),
$.getJSON("JSON3.json")
]).then(([data1, data2, data3]) => {
doingStuff(data1, data2, data3);
});
});