Подтвердить что ты не робот

Как я могу заставить выполнить выполнение JavaScript-кода до тех пор, пока не будет загружен и выполнен запрос AJAX с script?

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

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

Ответ 1

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

Поскольку вызов 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>

Ответ 3

Вы можете попробовать сделать синхронный вызов 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(){}
}

Ответ 4

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

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