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

Как сделать код javascript execute * в порядке *

Хорошо, поэтому я ценю, что Javascript - это не С# или PHP, но я продолжаю возвращаться к проблеме в Javascript - не с самой JS, а с ее использованием.

У меня есть функция:

function updateStatuses(){

showLoader() //show the 'loader.gif' in the UI

updateStatus('cron1'); //performs an ajax request to get the status of something
updateStatus('cron2');
updateStatus('cron3');
updateStatus('cronEmail');
updateStatus('cronHourly');
updateStatus('cronDaily');

hideLoader(); //hide the 'loader.gif' in the UI

}

Вещь из-за того, что Javascript сжигает желание перепрыгнуть вперед в коде, загрузчик никогда не появляется, потому что функция "hideLoader" работает сразу после.

Как я могу это исправить? Или, другими словами, как я могу выполнить функцию javascript в том порядке, в котором я пишу его на странице...

4b9b3361

Ответ 1

Проблема возникает из-за того, что AJAX по своей природе является асинхронным. Это означает, что вызовы updateStatus() действительно выполняются по порядку, но немедленно возвращаются, а интерпретатор JS достигает hideLoader(), прежде чем какие-либо данные будут получены из запросов AJAX.

Вы должны выполнить hideLoader() в событии, в котором завершены вызовы AJAX.

Ответ 2

Вам нужно думать о JavaScript как о событии, а не о процедуре, если вы программируете AJAX. Вам нужно дождаться завершения первого вызова перед выполнением второго. Способ сделать это - привязать второй вызов к обратному вызову, который срабатывает, когда первый закончен. Не зная больше о внутренней работе вашей библиотеки AJAX (надеюсь, вы используете библиотеку), я не могу сказать вам, как это сделать, но это, вероятно, будет выглядеть примерно так:

showLoader();

  updateStatus('cron1', function() {
    updateStatus('cron2', function() {
      updateStatus('cron3', function() {
        updateStatus('cronEmail', function() {
          updateStatus('cronHourly', function() {
            updateStatus('cronDaily', funciton() { hideLoader(); })
          })
        })
      })
    })
  })
});

Идея состоит в том, что updateStatus принимает свой обычный аргумент, плюс функция обратного вызова, которая должна выполняться по завершении. Это достаточно общий шаблон для передачи функции для запуска onComplete в функцию, которая предоставляет такой крючок.

Обновление

Если вы используете jQuery, вы можете прочитать здесь $.ajax(): http://api.jquery.com/jQuery.ajax/

Ваш код, вероятно, выглядит примерно так:

function updateStatus(arg) {
  // processing

  $.ajax({
     data : /* something */,
     url  : /* something */
  });

  // processing
}

Вы можете изменить свои функции, чтобы сделать обратный вызов в качестве своего второго параметра примерно так:

function updateStatus(arg, onComplete) {
  $.ajax({
    data : /* something */,
    url  : /* something */,
    complete : onComplete // called when AJAX transaction finishes
  });

}

Ответ 3

Я думаю, все, что вам нужно сделать, это иметь это в своем коде:

async: false,

Итак, ваш вызов Ajax будет выглядеть так:

jQuery.ajax({
            type: "GET",
            url: "something.html for example",
            dataType: "html",
            async: false,
            context: document.body,
            success: function(response){

                //do stuff here

            },
            error: function() {
                alert("Sorry, The requested property could not be found.");
            }  
        });

Очевидно, что некоторые из этих изменений необходимо изменить для XML, JSON и т.д., но async: false, является основным моментом здесь, который говорит JS-движку ждать, пока вызов успеха не вернется (или не сработает), а затем перенесет на. Помните, что есть недостаток в этом, и это означает, что вся страница становится невосприимчивой, пока аякс не вернется!!! обычно в миллисекундах, которые не являются крупными сделками, но МОГУТ длиться дольше.

Надеюсь, что это правильный ответ, и это поможет вам:)

Ответ 4

У нас есть что-то подобное в одном из наших проектов, и мы решили это, используя счетчик. Если вы увеличиваете счетчик для каждого вызова до updateStatus и уменьшаете его в функции ответа на запрос AJAX (зависит от используемой вами библиотеки JavaScript AJAX.)

Как только счетчик достигнет нуля, все запросы AJAX завершены, и вы можете вызвать hideLoader().

Здесь пример:

var loadCounter = 0;

function updateStatuses(){
    updateStatus('cron1'); //performs an ajax request to get the status of something
    updateStatus('cron2');
    updateStatus('cron3');    
    updateStatus('cronEmail');
    updateStatus('cronHourly');
    updateStatus('cronDaily');
}

function updateStatus(what) {
    loadCounter++;

    //perform your AJAX call and set the response method to updateStatusCompleted()
}

function updateStatusCompleted() {
    loadCounter--;
    if (loadCounter <= 0)
        hideLoader(); //hide the 'loader.gif' in the UI
}

Ответ 5

Это не имеет никакого отношения к порядку выполнения кода.

Причина, по которой изображение загрузчика никогда не отображается, заключается в том, что пользовательский интерфейс не обновляется во время работы вашей функции. Если вы вносите изменения в пользовательский интерфейс, они не отображаются, пока вы не выйдете из функции и не вернетесь в браузер.

Вы можете использовать таймаут после установки изображения, предоставляя браузеру возможность обновить интерфейс перед началом остальной части кода:

function updateStatuses(){

  showLoader() //show the 'loader.gif' in the UI

  // start a timeout that will start the rest of the code after the UI updates
  window.setTimeout(function(){
    updateStatus('cron1'); //performs an ajax request to get the status of something
    updateStatus('cron2');
    updateStatus('cron3');
    updateStatus('cronEmail');
    updateStatus('cronHourly');
    updateStatus('cronDaily');

    hideLoader(); //hide the 'loader.gif' in the UI
  },0);
}

Есть еще один фактор, который также может привести к тому, что ваш код будет работать не в порядке. Если ваши запросы AJAX асинхронны, функция не будет ждать ответов. Функция, которая отвечает за ответ, будет выполняться, когда браузер получит ответ. Если вы хотите скрыть изображение загрузчика после получения ответа, вам придется делать это, когда запускается последняя функция обработчика ответа. Поскольку ответы не должны поступать в том порядке, в котором вы отправили запросы, вам нужно будет подсчитать, сколько ответов вы узнаете, когда придет последний.

Ответ 6

Установите Firebug, затем добавьте строку, подобную этой, для каждого из showLoader, updateStatus и hideLoader:

Console.log("event logged");

В окне консоли вы увидите вызовы вашей функции, и они будут в порядке. Вопрос в том, что делает ваш метод "updateStatus"?

Предположительно, он запускает фоновое задание, а затем возвращается, поэтому вы дойдете до вызова hideLoader до завершения любой из фоновых задач. Возможно, ваша библиотека Ajax имеет ответ "OnComplete" или "OnFinished" - вызовите следующий updateStatus.

Ответ 7

Как отмечали другие, вы не хотите выполнять синхронную операцию. Объявите Async, что означает A в AJAX.

Я хотел бы упомянуть прекрасную аналогию с synyn v/s async. Вы можете прочитать весь пост на форуме GWT, я просто включаю соответствующие аналоги.

Представьте, если вы...

Ты сидишь на диване ТВ, и зная, что вы не в пиво, спросите своего супруга, пожалуйста сбегайте в магазин спиртных напитков и принеси тебе. Как только вы увидите ваш супруг выходит из передней двери, вы встаете с дивана и качаетесь на кухню и холодильник. К вашему удивлению, нет пиво!

Ну, конечно, пива нет, супруг все еще находится на пути к Ликеро-водочный магазин. Тебе нужно подождать, пока [s] он возвращается, прежде чем вы можете ожидать иметь пиво.

Но вы говорите, что хотите синхронно? Представьте себе снова...

... супруг выходит из двери... теперь, весь окружающий вас мир останавливается, вы не дышите, ответьте дверь или финиш смотрят ваше шоу в то время как он бежит по городу Принесите свое пиво. Вы просто сидите там не двигается мышца, а синяя, пока вы не потеряете сознание... пробуждение некоторых неопределенное время спустя, окруженное ЕМТ и супруг, говорящий о, эй, я получил ваше пиво.

Именно это происходит, когда вы настаиваете на синхронном вызове сервера.

Ответ 8

переместите вызовы updateStatus на другую функцию. сделайте вызов setTimeout с новой функцией в качестве цели.

Если ваши аякс-запросы являются асинхронными, у вас должно быть что-то, чтобы отслеживать, какие из них были выполнены. каждый метод обратного вызова может установить "завершенный" флаг где-то для себя и проверить, не делает ли это последнее. если это так, то попросите его вызвать hideLoader.

Ответ 9

Одним из лучших решений для обработки всех асинхронных запросов является "Promise" .
Объект Promise представляет собой возможное завершение (или отказ) асинхронной операции.

Пример:

let myFirstPromise = new Promise((resolve, reject) => {
  // We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed.
  // In this example, we use setTimeout(...) to simulate async code. 
  // In reality, you will probably be using something like XHR or an HTML5 API.
  setTimeout(function(){
    resolve("Success!"); // Yay! Everything went well!
  }, 250);
});  

myFirstPromise.then((successMessage) => {
  // successMessage is whatever we passed in the resolve(...) function above.
  // It doesn't have to be a string, but if it is only a succeed message, it probably will be.
  console.log("Yay! " + successMessage);
});

Promise

Если у вас есть 3 асинхронные функции и вы ожидаете запустить их в порядке, выполните следующие действия:

let FirstPromise = new Promise((resolve, reject) => {
    FirstPromise.resolve("First!");
});
let SecondPromise = new Promise((resolve, reject) => {

});
let ThirdPromise = new Promise((resolve, reject) => {

});
FirstPromise.then((successMessage) => {
  jQuery.ajax({
    type: "type",
    url: "url",
    success: function(response){
        console.log("First! ");
        SecondPromise.resolve("Second!");
    },
    error: function() {
        //handle your error
    }  
  });           
});
SecondPromise.then((successMessage) => {
  jQuery.ajax({
    type: "type",
    url: "url",
    success: function(response){
        console.log("Second! ");
        ThirdPromise.resolve("Third!");
    },
    error: function() {
       //handle your error
    }  
  });    
});
ThirdPromise.then((successMessage) => {
  jQuery.ajax({
    type: "type",
    url: "url",
    success: function(response){
        console.log("Third! ");
    },
    error: function() {
        //handle your error
    }  
  });  
});

При таком подходе вы можете обрабатывать все операции async по своему усмотрению.