2012-03-28 4 views
1

Я хотел бы предисловие к этому с извинениями, если я делаю вещи «странным» способом, так как я в первую очередь разработчик C и решаю эту проблему AJAX так, C.JavaScript синхронный запрос Ajax Idodayncrasies

У меня есть сценарий, который будет подключаться к «push-серверу», который ждет, пока сообщение будет доступно, затем отправит только одно сообщение и разрывает соединение. Затем клиент должен восстановить соединение для прослушивания будущих сообщений.

Я пытался сделать это путем реализации синхронной AJAX вызова в пределах асинхронного обратного вызова, и она работает за исключением того, появляется DOM (может быть? Я показываю свое невежество JS здесь) не будет блокировать до все звонки завершены.

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

Это код:

 $.ajax({ 
      url: './recoverDevice', 
      data: JSON.stringify(requestData), 
      dataType: 'json', 
      type: 'POST', 
      success: function(j) 
      { 
       console.log(j); 
       if (j.success) 
       { 
        //Indefinitely listen for push messages from the server 

        var loopMore = true; 
        while(loopMore) 
        { 
         $.ajax({ 
          async: false, 
          url: './getPendingMessage', 
          dataType: 'json', 
          type: 'POST', 
          success: function(j) 
          { 
           //alert(j.message); 
           $("#progressBox").append("<li>" + j.message + "</li>"); 
           loopMore = !j.complete; 
          } 
         }); 
        } 

       } 
       else 
       { 
        $("#errorBox").show(); 
        $("#errorBox").text(j.errorMessage); 
       } 
      } 
     }); 

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

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

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

Я предполагаю, что это мой браузер (Chrome), делающий магию для защиты от условий гонки, не допуская манипуляции DOM до выхода асинхронной нити? Или я нахожусь в стороне от знака и лаем здесь неправильное дерево?

Избавление от цикла и установка async на значение true, чтобы первое сообщение принималось должным образом (никаких проблем там нет), но, очевидно, после этого сообщений нет.

Очевидно, что я мог бы сделать что-то вроде этого:

function GetMessage() 
{ 
    $.ajax({ 
     async: true, 
     url: './getPendingMessage', 
     dataType: 'json', 
     type: 'POST', 
     success: function(j) 
     { 
      $("#progressBox").append("<li>" + j.message + "</li>"); 
      if (!j.complete) 
      { 
       GetMessage(); 
      } 
     } 
    }); 
} 

Но это приведет к переполнению стека с течением времени (нет?).

Очевидным решением было бы использовать асинхронные вызовы здесь, но чтобы сигнализировать цикл while для приостановки и продолжения новых вызовов через какие-то примитивы синхронизации, но похоже, что у JS нет сигнальных примитивов?

ответ

0

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

Я по-прежнему признателен за любые данные о том, почему первый метод (синхронный код при асинхронном вызове) не работал/не работал.

+0

Причина, по которой первый метод «не работал», был просто функцией алгоритма перерисовки браузера. Однопоточный синхронный js блокируется, так что, пока поток обрабатывается, браузер не перерисовывает. Однако он перерисовывается, когда появляется окно предупреждения (код по-прежнему синхронный и в некотором смысле блокирующий, но под капотом я полагаю, что он имеет ожидающее/неблокирующее состояние в том, что касается алгоритма перерисовывания), поэтому он предположительно выглядел нормально с предупреждением. Просто нюансы реализации. – davin

+0

Но синхронный js-код вызывался из уже асинхронного потока js ..? –

+1

Это не имеет значения, я не уверен, почему вы так думаете. «Асинхронная нить» на самом деле не имеет большого значения. Когда кусок кода возвращается в цикл событий, он неотличим от любого другого фрагмента кода, поэтому независимо от того, началось ли его выполнение синхронно или нет, текущее выполнение является синхронным. Это похоже на людей, прибывающих на вечеринку, хотя некоторые люди ходят, а другие приходят на машине (синхронно или асинхронно, по общему признанию, не самая лучшая аналогия), как только они приходят, они проверяются по безопасности один за другим. – davin

Смежные вопросы