私のアプリケーションでは、Ext.Ajax.request
は、eval
で実行するスクリプトをロードします。
問題は、AJAXリクエストの完了に時間がかかるため、AJAXを介してロードされたスクリプトにある変数を必要とする後で実行されるコードです。この例では、 AJAXの後のJavaScriptの実行がAJAX呼び出しのスクリプトがロードされ、処刑?
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>
これは、XMLHttpRequest
オブジェクトを作成し、asyncパラメータをfalseに設定して open 関数を呼び出すことで実現できます。
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "ajax_info.txt", false);
var response = xmlhttp.responseText;
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(){}
}