我正在努力更好地了解回调的工作原理。
在这个例子中,我想使用AJAX获取两个或更多XML文件,然后从中提取我需要的内容,然后将这些数据存储在AJAX调用之外的数组中。我想使用“dataExt”数组来绘制谷歌图表,但我正在挂断正确实现回调。我猜我的大脑还不够大!
这是我的代码段。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
// List of xml files.
var xmlFeed = ['rss-feed1.xml', "rss-feed2.xml"];
// An array to store each "dataString" from each XML file.
var dataExt = [];
for(var i = 0; i < xmlFeed.length; i++) {
$.ajax({
type: "GET",
dataType: "xml",
async: true,
url: xmlFeed[i],
contentType: "text/xml; charset=UTF-8",
success: function(xml){
var content = $(xml).find("content");
var dataString = (content.text());
console.log(dataString);
// Need to push "dataString" to "dataExt" array.
// dataExt = dataExt.push(dataString); <-- this doesn't work
}
}) // close ajax
} // close loop
console.log(dataExt[0]);
console.log(dataExt[1]);
</script>
答案 0 :(得分:2)
当您发出AJAX请求时,对$ .ajax()的调用会立即返回。它不会等待内容通过网络返回。在您的示例中,在回调完成之前调用console.log()语句。
您想要的是一次回调,一旦获取了各种请求所需的所有数据,就会执行该回调。为此,您需要在您正在执行的各种AJAX调用之间进行某种同步。仅jQuery不支持这一点。
你可以自己动手。但是,这是一个足够普遍的设计问题,整个库都已经编写来处理它。
在Promise模式上做一些Google搜索。完成后,请查看Q库,这是该模式的几种实现之一。他们完成了为您同步多个AJAX请求的大部分艰苦工作。
示例:
function xmlPromise(name) {
return Q.promise(function (resolve, reject, notify) {
$.ajax({
type: "GET",
dataType: "xml",
async: true,
url: name,
contentType: "text/xml; charset=UTF-8"
})
.done(function (data) {
resolve(data);
}).fail(function () {
reject();
});
});
};
var promises = [ xmlPromise('1.xml'), xmlPromise('2.xml') ];
var results = [];
Q.allSettled(promises).then(function(responses) {
console.log(responses[0].value);
console.log(responses[1].value);
results.push(responses[0].value);
results.push(responses[1].value);
});
在此示例中,xmlPromise()函数根据您要获取的URL为您创建一个promise对象。这个承诺代表了将在未来某个时间完成的工作单元。当你在promise中创建的AJAX调用成功返回时,它会调用resolve()方法,让Q知道已经履行了promise,并且数据已经可以使用了。
一旦构造了promise,我们将它们的数组传递给Q.allSettled(),它实际上会触发请求。因为这些请求是异步的,所以它们是并行执行的。一旦所有的promise都被解析或被拒绝,Q将调用你传递给then()方法的函数,并传入你的AJAX调用的结果。
答案 1 :(得分:0)
在请求完成之前触发控制台日志。
希望这个例子是你的意思:
function getXml(file, successCallback){
$.ajax({
type: "GET",
dataType: "xml",
async: true,
url: file,
contentType: "text/xml; charset=UTF-8",
success: successCallback
}) // close ajax
}
function sc(xml){
var content = $(xml).find("content");
var dataString = (content.text());
console.log(dataString);
// Need to push "dataString" to "dataExt" array.
// dataExt = dataExt.push(dataString); <-- this doesn't work
// do whatever else you want next
}
pages ['1.xml', '2.xml'].forEach(function(v, i){
getXml(v, sc);
})