[英]How can I get make JavaScript code execution to wait until an AJAX request with script is loaded and executed?
在我的應用程序中,我使用Ext.Ajax.request
來加載我用eval
執行的腳本。
問題是,由於AJAX請求需要一段時間才能完成,之后執行的代碼需要通過AJAX加載的腳本中的變量。 在這個例子中,我展示了這種情況。 如何更改此代碼,以便在AJAX等待直到AJAX調用中的腳本加載並執行后執行JavaScript?
testEvalIssue_script.htm:
<script type="text/javascript">
console.log('2. inside the ajax-loaded script');
</script>
main.htm中:
<html>
<head>
<script type="text/javascript" src="ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext/ext-all-debug.js"></script>
<script type="text/javascript">
function loadViewViaAjax(url) {
Ext.Ajax.request({
url: url,
success: function(objServerResponse) {
var responseText = objServerResponse.responseText;
var scripts, scriptsFinder=/<script[^>]*>([\s\S]+)<\/script>/gi;
while(scripts=scriptsFinder.exec(responseText)) {
eval.call(window,scripts[1]);
}
}
});
}
console.log('1. before loading ajax script');
loadViewViaAjax('testEvalIssue_script.htm');
console.log('3. after loading ajax script');
</script>
</head>
<body>
</body>
</html>
輸出:
1. before loading ajax script
3. after loading ajax script
2. inside the ajax-loaded script
如何使輸出的順序正確,如下所示:
1. before loading ajax script
2. inside the ajax-loaded script
3. after loading ajax script
Ajax是異步的,這意味着調度了ajax調用,但是你的代碼在不停止的情況下繼續像以前一樣運行。 在收到響應之前,Ajax不會停止/暫停執行。 你必須添加一個額外的回調函數或類似的東西。
<html>
<head>
<script type="text/javascript" src="ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext/ext-all-debug.js"></script>
<script type="text/javascript">
function loadViewViaAjax(url, callback) {
Ext.Ajax.request({
url: url,
success: function(objServerResponse) {
var responseText = objServerResponse.responseText;
var scripts, scriptsFinder=/<script[^>]*>([\s\S]+)<\/script>/gi;
while(scripts=scriptsFinder.exec(responseText)) {
eval.call(window,scripts[1]);
}
callback.call();
}
});
}
console.log('1. before loading ajax script');
var afterAjax = function(){
console.log('3. after loading ajax script');
}
loadViewViaAjax('testEvalIssue_script.htm', afterAjax);
</script>
</head>
<body>
</body>
</html>
由於ajax調用是異步的,如果你想執行依賴於通過ajax加載的數據的東西,你必須在success方法中執行它。 將代碼放在另一個方法中,然后在eval語句之后調用該方法。
<script type="text/javascript">
function doSomeAmazingThings() {
// amazing things go here
}
function loadViewViaAjax(url) {
Ext.Ajax.request({
url: url,
success: function(objServerResponse) {
var responseText = objServerResponse.responseText;
var scripts, scriptsFinder=/<script[^>]*>([\s\S]+)<\/script>/gi;
while(scripts=scriptsFinder.exec(responseText)) {
eval.call(window,scripts[1]);
}
doSomeAmazingThings();
console.log('3. after loading ajax script');
}
});
}
console.log('1. before loading ajax script');
loadViewViaAjax('testEvalIssue_script.htm');
</script>
您可以嘗試使AJAX調用同步...當然您必須停止使用Ext.Ajax庫,但如果您需要在下一行代碼之前獲得ajax結果,那么它是值得的。
這就是我的內部網頁與我的數據庫通信的方式。 我發現有一個挫折,因為在Javascript放棄控制權返回頁面之前你看不到任何頁面更新,因此同步Ajax不可能有狀態欄,進度條或疊加層(對於我的firefox不適用) ,在某些情況下甚至會在同步代碼內更新)。
我使用它 - 它有點本土和雜亂,但它在我的圈子里多年來完美無瑕地工作。 只需創建一個新的AJAX(),設置url,根據需要添加查詢(名稱/值對),將異步設置為false,當從函數調用Execute時,它將阻塞直到Ajax返回。
或者,如果要異步使用它,只需為您創建的AJAX對象編寫一個新的“onready”函數,並將異步更改為true。
我多年前寫過這篇文章,所以它不是最好的,而且有辦法以不同的方式做事,但它可以作為一個入門書,你可以隨意調整它,而不必依賴於另一個庫。
function AJAX(){
//Declarations
var thisExt=this; //To be referenced by events
//Initialize Properties
thisExt.URL="";
thisExt.Query="";
thisExt.Method="GET";
thisExt.Asynchronous=true;
thisExt.Encoding="application/x-www-form-urlencoded";
thisExt.PostData="";
// Provide the XMLHttpRequest class for IE 5.x-6.x:
// Other browsers (including IE 7.x-8.x) ignore this
// when XMLHttpRequest is predefined
if (typeof XMLHttpRequest == "undefined") {
try {
thisExt.XMLHTTP = new ActiveXObject("Msxml2.XMLHTTP.6.0");
}
catch (e1) {
try { thisExt.XMLHTTP = new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
catch (e2) {
try { thisExt.XMLHTTP = new ActiveXObject("Msxml2.XMLHTTP"); }
catch (e3) {
try { thisExt.XMLHTTP = new ActiveXObject("Microsoft.XMLHTTP"); }
catch (e4) {
throw new Error("This browser does not support XMLHttpRequest.");
}
}
}
}
} else {
thisExt.XMLHTTP = new XMLHttpRequest();
}
//Methods
thisExt.XMLHTTP.onreadystatechange = function(){
if(thisExt.XMLHTTP.readyState==4){
window.status="";
thisExt.onready(thisExt);//Passes thisExt so that the callback will have assess to the entire object, not just the returned text.
}else{
window.status=thisExt.XMLHTTP.readyState;//Just for debugging
}
}
thisExt.addQuery=function(name,value){
if(thisExt.Query!=""){
thisExt.Query+="&"
}
thisExt.Query+=encodeURIComponent(name)+"="+encodeURIComponent(value)
}
//Not really necessary, you could just say AjaxObj.URL="bla bla"
thisExt.setURL=function(URL){
thisExt.URL=URL;
}
//Not really necessary, you could just say AjaxObj.Query="bla bla"
thisExt.setQuery=function(Query){
thisExt.Query=Query;
}
//Not really necessary, you could just say AjaxObj.Method="bla bla"
thisExt.setMethod=function(Method){
thisExt.Method=Method;
}
//Not really necessary, you could just say AjaxObj.Encoding="bla bla"
thisExt.setEncoding=function(Encoding){
thisExt.Encoding=Encoding;
}
//Not really necessary, you could just say AjaxObj.PostData="bla bla"
thisExt.setPostData=function(PostData){
thisExt.PostData=PostData;
}
thisExt.Execute=function(){
if(thisExt.URL==""){
alert("AJAX.URL cannot be null.")
return;
}
var URL2=thisExt.URL;
if(thisExt.Query!=""){
URL2=URL2+"?"+thisExt.Query;
}
if(thisExt.Method=="POST"){
//this.XMLHTTP.setRequestHeader("Content-Type",this.Encoding);
thisExt.XMLHTTP.open("POST", URL2, thisExt.Asynchronous);
thisExt.XMLHTTP.send(thisExt.PostData);
} else {
thisExt.XMLHTTP.open("GET", URL2, thisExt.Asynchronous);
thisExt.XMLHTTP.send(null);
}
}
//Events & callbacks
thisExt.onready=function(){}
}
這可以通過創建XMLHttpRequest
對象並在async參數設置為false的情況下調用open函數來實現。
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "ajax_info.txt", false);
var response = xmlhttp.responseText;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.