我需要从服务器加载一个JSON文件,稍后我会用它来填充网站上的内容。使用XMLHttpRequest
加载JSON文件应该是异步的,并且可以尽快发生。然而,填充内容需要加载DOM。
现在,我调用xhr.open('GET', 'records.json', false)
使请求同步。这需要花费更多时间来加载和解析JSON,而不是浏览器加载DOM。当发生这种情况时(即连接速度很慢),将加载DOM,DOMContentLoaded
事件监听器中的代码将在仍然listData
的{{1}}上执行。坏。
如何使用异步undefined
并同时在XMLHttpRequest
上执行我的代码?我想在DOMContentLoaded
完全加载后执行我的代码(即完成listData
)并且DOM可用。当两个条件都满足时,我很高兴。
JSON.parse()
答案 0 :(得分:1)
当我需要等待几个异步事件时,我的个人方法通常是这样的:
const EVENT0 = 0x1;
const EVENT1 = 0x2;
const ALL_READY = 0x3;
var ready = 0;
init();
function init() {
asyncRequest0();
asyncRequest1();
var waitFunc;
(waitFunc = function() {
if(ready == ALL_READY) {
goOn();
}
else {
setTimeout(waitFunc, 10);
}
})();
}
function goOn() {
console.log('Here we go!');
}
function asyncRequest0() {
// some callback will do:
ready |= EVENT0;
}
function asyncRequest1() {
// some callback will do:
ready |= EVENT1;
}
所以基本上,每个异步事件都会在“准备好”中设置一个位。一旦工作完成,就变量。 waitFunc()函数将耐心地等待所有事件完成(无论以何种顺序)并调用goOn()函数。
现在,应用于您的代码:
const DOM_READY = 0x1;
const XHR_READY = 0x2;
const ALL_READY = 0x3;
var ready = 0;
var listData;
init();
function init() {
document.addEventListener("DOMContentLoaded", function() {
ready |= DOM_READY;
});
var xhr = new XMLHttpRequest();
xhr.open('GET', 'records.json', false);
xhr.addEventListener("load", function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
listData = JSON.parse(xhr.responseText);
} else {
listData = false;
console.error('Error: ' + xhr.status + ' ' + xhr.statusText);
}
ready |= XHR_READY;
}
});
xhr.addEventListener("error", function() {
listData = false;
ready |= XHR_READY;
console.error('Error: ' + xhr.status + ' ' + xhr.statusText);
});
xhr.send(null);
var waitFunc;
(waitFunc = function() {
if (ready == ALL_READY) {
goOn();
} else {
setTimeout(waitFunc, 10);
}
})();
}
function goOn() {
console.log('Here we go!');
// do something with listData
}
这里只有2个事件不需要位掩码,但它是一次测试多个事件的便捷方式。
答案 1 :(得分:1)
您可以使用promise和async get请求,并将成功返回的数据附加到DOMContentLoaded
回调中可用的内容中,您可以在其中重复检查数据是否已分配。
let myData;
let doAsyncOperation = (param) => {
if ( window.Promise ) {
let promise = new Promise( (resolve, reject) => {
// Do your async request here...
window.setTimeout(() => {
// resolve the promise with successfully returned data from get req.
resolve(`Hello ${param}`)
}, 1000);
// reject the promise if your request returns an error
if (typeof param !== "string") reject("param must be a string");
})
return promise;
} else {
console.log("Sorry no promise for you, use a fallback ")
}
}
doAsyncOperation("Foo !").then(
// on success do something with your data.
(data) => myData = data,
(err) => console.log(err)
);
// Inside DOMContentLoaded callback check if myData is available.
document.addEventListener("DOMContentLoaded", (event) => {
let loop = () => {
(myData) ? console.log(myData) : window.setTimeout(loop, 100);
};
loop();
});