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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5354641/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:49:32  来源:igfitidea点击:

How can I get make JavaScript code execution to wait until an AJAX request with script is loaded and executed?

javascriptajaxextjscallback

提问by Edward Tanguay

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

在我的应用程序中,我使用Ext.Ajax.request加载脚本,我使用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,直到加载并执行 AJAX 调用中的脚本?

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

采纳答案by ChrisR

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>

回答by Robby Pond

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>

回答by alfadog67

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).

这就是我的 Intranet 页面与我的数据库通信的方式。我发现了一个挫折,因为在 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(){}
}

回答by Mahmood Khan

This can be achieved by creating an XMLHttpRequestobject and calling the openfunction 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;