如何让JavaScript代码执行等待加载并执行带有脚本的AJAX请求?

时间:2022-08-23 17:56:01

In my application, I am using Ext.Ajax.request to load scripts which I execute with eval.

在我的应用程序中,我使用的是Ext.Ajax。请求加载我用eval执行的脚本。

The problem is that since it takes time for the AJAX request to complete, code that is executed afterward which needs variables which are in the script loaded in via AJAX. In this example, I show how this is the case. How can I change this code so that the execution of the JavaScript after the AJAX waits until the script in the AJAX call has been loaded and executed?

问题是,由于AJAX请求需要时间来完成,所以后面执行的代码需要通过AJAX加载的脚本中的变量。在这个例子中,我展示了这个例子。我如何更改此代码以便在AJAX调用的脚本加载并执行之后,JavaScript的执行被执行?

testEvalIssue_script.htm:

testEvalIssue_script.htm:

<script type="text/javascript">
    console.log('2. inside the ajax-loaded script');
</script>

main.htm:

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>

output:

输出:

1. before loading ajax script
3. after loading ajax script
2. inside the ajax-loaded script

How can I get the output to be in the correct order, like this:

如何使输出按正确的顺序排列,例如:

1. before loading ajax script
2. inside the ajax-loaded script
3. after loading ajax script

4 个解决方案

#1


12  

Ajax is asynchronous, that means that the ajax call is dispatched but your code keeps on running as happy as before without stopping. Ajax doesn't stop/pause execution until a response is received. You'll have to add an extra callback function or something like that.

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>

#2


3  

Since the ajax call is asynchronous, if you want to execute something that depends on data loaded via ajax, you will have to execute it in the success method. Put the code in another method, and then call that method after the eval statements.

由于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>

#3


1  

You could try making the AJAX call synchronous... Of course you'd have to stop using the Ext.Ajax library, but it's worth it if you need ajax results before your next line of code.

您可以尝试使AJAX调用同步……当然,您必须停止使用Ext.Ajax库,但是如果您需要在下一行代码之前获得ajax结果,那么它是值得的。

That's how my intranet pages communicate with my database. There's a setback I've discovered, in that you can't see any page updates until Javascript relinquishes control back to the page, so things like a status bar, a progress bar or overlay are impossible with synchronous Ajax (Not true for my firefox, it updates even inside synchronous code in some circumstances).

这就是我的内部网页面与数据库的通信方式。我发现有一个挫折,因为你不能看到任何Javascript页面更新,直到放弃控制页面,所以一个状态栏,一个进度条或覆盖是不可能同步Ajax(不是真的为我的firefox,它甚至更新内部同步代码在某些情况下)。

I use this - it's a bit home-grown and messy, but it's worked flawlessly for years in my circle. Just create a new AJAX(), set the url, add queries (name/value pairs) as needed, set asynchronous to false, and when you call Execute from a function, it will block until the Ajax returns.

我用这个——它有点本土化和凌乱,但它在我的圈子里已经完美地工作了很多年。只需创建一个新的AJAX(),设置url,根据需要添加查询(名称/值对),将异步设置为false,当您从函数调用Execute时,它将阻塞,直到AJAX返回。

Or, if you want to use it asynchronously, just write a new "onready" function for tha AJAX object you create, and change asynchronous to true.

或者,如果您想异步使用它,只需为您创建的AJAX对象编写一个新的“onready”函数,并将异步更改为true。

I wrote this many years ago, so it's not the neatest, and there are ways to do things differently, but it works as a primer, and you can tweak it however you like without having to depend on another library.

这是我多年前写的,所以它不是最整洁的,有很多方法可以做不同的事情,但是作为入门,你可以随意调整它,而不必依赖于其他库。

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(){}
}

#4


1  

This can be achieved by creating an XMLHttpRequest object and calling the open function with the async parameter set to false.

这可以通过创建XMLHttpRequest对象并调用open函数来实现,并将async参数设置为false。

var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "ajax_info.txt", false);
var response = xmlhttp.responseText;

#1


12  

Ajax is asynchronous, that means that the ajax call is dispatched but your code keeps on running as happy as before without stopping. Ajax doesn't stop/pause execution until a response is received. You'll have to add an extra callback function or something like that.

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>

#2


3  

Since the ajax call is asynchronous, if you want to execute something that depends on data loaded via ajax, you will have to execute it in the success method. Put the code in another method, and then call that method after the eval statements.

由于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>

#3


1  

You could try making the AJAX call synchronous... Of course you'd have to stop using the Ext.Ajax library, but it's worth it if you need ajax results before your next line of code.

您可以尝试使AJAX调用同步……当然,您必须停止使用Ext.Ajax库,但是如果您需要在下一行代码之前获得ajax结果,那么它是值得的。

That's how my intranet pages communicate with my database. There's a setback I've discovered, in that you can't see any page updates until Javascript relinquishes control back to the page, so things like a status bar, a progress bar or overlay are impossible with synchronous Ajax (Not true for my firefox, it updates even inside synchronous code in some circumstances).

这就是我的内部网页面与数据库的通信方式。我发现有一个挫折,因为你不能看到任何Javascript页面更新,直到放弃控制页面,所以一个状态栏,一个进度条或覆盖是不可能同步Ajax(不是真的为我的firefox,它甚至更新内部同步代码在某些情况下)。

I use this - it's a bit home-grown and messy, but it's worked flawlessly for years in my circle. Just create a new AJAX(), set the url, add queries (name/value pairs) as needed, set asynchronous to false, and when you call Execute from a function, it will block until the Ajax returns.

我用这个——它有点本土化和凌乱,但它在我的圈子里已经完美地工作了很多年。只需创建一个新的AJAX(),设置url,根据需要添加查询(名称/值对),将异步设置为false,当您从函数调用Execute时,它将阻塞,直到AJAX返回。

Or, if you want to use it asynchronously, just write a new "onready" function for tha AJAX object you create, and change asynchronous to true.

或者,如果您想异步使用它,只需为您创建的AJAX对象编写一个新的“onready”函数,并将异步更改为true。

I wrote this many years ago, so it's not the neatest, and there are ways to do things differently, but it works as a primer, and you can tweak it however you like without having to depend on another library.

这是我多年前写的,所以它不是最整洁的,有很多方法可以做不同的事情,但是作为入门,你可以随意调整它,而不必依赖于其他库。

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(){}
}

#4


1  

This can be achieved by creating an XMLHttpRequest object and calling the open function with the async parameter set to false.

这可以通过创建XMLHttpRequest对象并调用open函数来实现,并将async参数设置为false。

var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "ajax_info.txt", false);
var response = xmlhttp.responseText;