Рабочий процесс AJAX: Как мне заказать выполнение этих функций? - PullRequest
0 голосов
/ 06 ноября 2010

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

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

функция 1 - впрыскивает ОПЦИИ в SELECT через JSON и помечает их как выбранные
функция 2 - впрыскивает OPTIONS во второй SELECT и помечает их как выбранные
функция 3 - получает значения из вышеупомянутых SELECTs вместе с некоторыми дополнительными значениями INPUT, выполняет AJAX GET, приводя к данным JSON, которые читаются и заполняют таблицу.

С JQuery Onload я выполняю:

function1();
function2();
function3();

Я обнаружил, что функция 3 выполняется до того, как SELECT заполнены OPTIONS, и, следовательно, таблица не имеет результатов, поскольку значения, отправленные в GET, были пустыми.

Я знаю, что это, вероятно, очень простая проблема и что, вероятно, существует дюжина способов сделать это, но в основном мне нужен лучший способ кодировать это, чтобы функция 3 выполнялась только тогда, когда функции 1 и 2 завершены.

Я зашел в Javascript через заднюю дверь, сначала изучив основы JQuery!

Спасибо за вашу помощь.

Ответы [ 5 ]

1 голос
/ 09 декабря 2010

Я рекомендую использовать библиотеку Promises .Вы можете взломать простые решения, как предлагают другие ответы, но по мере роста вашего приложения вы обнаружите, что делаете все больше и больше этих взломов.Обещания предназначены для решения подобных проблем при работе с асинхронными вызовами.

В проекте CommonJS есть несколько предложений Обещаний , которые вы должны проверить.Вот вопрос, который я задал на SO об обещаниях некоторое время назад со ссылками на другие решения.Узнайте больше об обещаниях в этом видео Дугласа Крокфорда .В целом видео хорошее, но переходите к обещаниям чуть позже.

В настоящее время я использую библиотеку FuturesJS , поскольку она соответствует моим потребностям.Но есть и преимущества для других реализаций.Это позволяет вам очень легко выполнить sequences:

// Initialize Application
Futures.sequence(function (next) { 
    // First load the UI description document
    loadUI(next);  // next() is called inside loadUI
})
.then(function(next) {
    // Then load all templates specified in the description
    loadTemplates(next); // next() is called inside loadTemplates
})
.then(function(next) {
    // Then initialize all templates specified in the description
    initTemplates();
});

Еще более мощным является тот случай, когда вам нужно join объединить асинхронные события и выполнить другое действие, когда все остальные асинхронные события завершены.Вот пример (не проверенный), который загрузит несколько файлов HTML и затем выполнит действие только после того, как ВСЕ из них завершат загрузку:

var path = "/templates/",
    templates = ["one.html","two.html","three.html"],
    promises = [];

$.each(templates, function(i,name) {
    promises[i] = Futures.promise();
    var $container = $("<div>");
    $container.load(path+name, function(response,status,xhr) {
        promises[i].fullfill();
    }
});

Futures.join(promises, {timeout: 10000}) // Fail if promises not completed in 10 seconds
    .when(function(p_arr) {
        console.log("All templates loaded");
    })
    .fail(function(p_arr) {
        console.log("Error loading templates");
    });

Это может быть излишним для вашего приложения.Но если приложение становится все сложнее, использование обещаний поможет вам в долгосрочной перспективе.

Надеюсь, это поможет!

1 голос
/ 06 ноября 2010

Javascript выполняется синхронно, что означает, что function3 должен ждать завершения function2, что должно ждать завершения function1 перед выполнением.

Исключение составляют случаи, когда вы выполняете асинхронный код, например setTimeout, setInterval или асинхронный запрос AJAX.

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

В случае setTimeout вы можете просто поместить следующий вызов функции в конец функции, которую вы передаете setTimeout.

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

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

Что-то вроде:

function function1( fn ) {
    setTimeout(function() {
        // your code 
        // Call the function parameter if it exists
        if( fn ) {
            fn();
        }
    }, 200);
}

function function2() {
    // some code that must wait for function1
}

OnLoad:

// Call function1 and pass function2 as an argument
function1( function2 );

// ...or call function1 without the argument
function1();

// ...or call function2 independently of function1
function2();
0 голосов
/ 06 ноября 2010

fun3 () будет запускаться только после того, как оба будут готовы.Это может работать дважды.Вы можете исправить это с помощью блокировки внутри fun3 (), вам понадобится Singleton, чтобы гарантировать его правильную работу.

var select1ready = false, select2ready = false;

fun1()
{
   // do stuff
   select1ready = true;
   fun3();
}

fun2()
{
  // do stuff
  select2ready = true;
  fun3();
}

fun3()
{
   if (select1ready && select2ready)
   {
   }
}


fun1();
fun2();
0 голосов
/ 06 ноября 2010

Непонятно, почему f1 и f2 выполняются до f3.

Кроме того, вы используете предпочтительный $ (document) .ready () или какой-либо вариант загрузки?

Может быть полезно, если вы предоставите воспроизводимый контрольный пример.

0 голосов
/ 06 ноября 2010

вызывает function2 внутри function1 и function3 внутри function2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...