Как получить выполнение кода JavaScript для ожидания загрузки и выполнения AJAX-запроса со сценарием? - PullRequest
17 голосов
/ 18 марта 2011

В моем приложении я использую Ext.Ajax.request для загрузки скриптов, которые я выполняю с eval.

Проблема в том, что, поскольку для выполнения запроса AJAX требуется время, код, который выполняется позже, требует переменных, которые в скрипте загружаются через AJAX. В этом примере я покажу, как это происходит. Как я могу изменить этот код так, чтобы выполнение JavaScript после AJAX ожидало загрузки и выполнения скрипта в вызове 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

Ответы [ 4 ]

12 голосов
/ 19 марта 2011

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>
3 голосов
/ 18 марта 2011

Поскольку вызов ajax является асинхронным, если вы хотите выполнить что-то, зависящее от данных, загруженных через ajax, вам придется выполнить это в методе успеха.Поместите код в другой метод, а затем вызовите этот метод после операторов 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>
1 голос
/ 29 августа 2013

Этого можно достичь, создав объект XMLHttpRequest и вызвав функцию open с параметром async, установленным в false.

var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "ajax_info.txt", false);
var response = xmlhttp.responseText;
1 голос
/ 08 декабря 2012

Вы можете попробовать сделать синхронный вызов AJAX ... Конечно, вам придется прекратить использование библиотеки Ext.Ajax, но это того стоит, если вам нужны результаты ajax перед следующей строкой кода.

Так страницы моей интрасети связываются с моей базой данных.Я обнаружил недостаток, заключающийся в том, что вы не можете видеть какие-либо обновления страницы, пока Javascript не откажется от управления обратно на страницу, поэтому такие вещи, как строка состояния, индикатор выполнения или наложение, невозможны с синхронным Ajax (не верно для моего firefox, он обновляется даже внутри синхронного кода при некоторых обстоятельствах.)

Я использую это - оно немного доморощенное и грязное, но в моем кругу годами оно работало без нареканий.Просто создайте новый AJAX (), установите URL-адрес, добавьте запросы (пары имя / значение) по мере необходимости, установите асинхронное значение false, и при вызове Execute из функции он будет блокироваться до тех пор, пока Ajax не вернется.* Или, если вы хотите использовать его асинхронно, просто напишите новую функцию «onready» для создаваемого вами AJAX-объекта и измените асинхронный на 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(){}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...