Как управлять потоками JavaScript и перерисовкой в ​​IE7 - PullRequest
0 голосов
/ 22 октября 2010

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

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

I 'Что-то вроде n00b со всем, что связано с javascript-in-the-browser, есть ли очевидная ошибка, которую я делаю, или хороший ресурс, чтобы узнать, как это сделать?


Обновление - образец

// called onReady()
function init() {
    doFirstThing();
    updateDisplayForFirstThing();
    doSecondThingWithAjaxCall();
    updateDisplayForSecondThing();
    ...
    reportAllLoaded();
}

Ответы [ 3 ]

1 голос
/ 22 октября 2010

Это можно исправить во многих случаях, используя обратные вызовы , особенно с вызовами AJAX - например:

function doFirstThing(fn){
  // doing stuff
  if(typeof fn == 'function') fn();
}

function updateDisplayForFirstThing(){
  // doing other stuff
}

function init(){
  doFirstThing(updateDisplayForFirstThing);
}

Другой вариант - использовать возвращаемые значения:

function doFirstThing(fn){
  // doing stuff
  if(x) return true;
  else return false;
}

function updateDisplayForFirstThing(){
  // doing other stuff
  return true;
}

function init(){
  if(doFirstThing()){ updateDisplayForFirstThing(); }
}

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

Тем не менее, иногда вам может понадобиться использовать setTimeout, чтобы убедиться, что DOM правильно обновился после определенных действий.

1 голос
/ 22 октября 2010

Если в конечном итоге вы решите, что вам нужна некоторая многопоточность JavaScript, посмотрите на все еще составляемый Web Workers API . Поддержка браузеров популярна, хотя API реализован в большинстве современных веб-браузеров.

Вопрос: как именно вы определили, когда «документ готов»? Событие DOMContentLoaded не поддерживается в IE. Я вполне уверен ... если вам нужно дождаться полной загрузки документа, вы можете использовать что-то вроде этого:

var onReady = function(callback) {
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", callback, false);
        return true;
    } else if (document.attachEvent) {
        var DOMContentLoaded = function() {
            if (document.readyState === "complete") {
                document.detachEvent("onreadystatechange", DOMContentLoaded);
                onReady();
            }
        };
        return true;
    }
};

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

Или вы можете просто включить сценарий в нижней части вашего тела ...

Я просто болтаю, пока у вас нет кода, чтобы показать нам?

1 голос
/ 22 октября 2010

IE не будет обновлять отображение, пока текущий скрипт не завершит работу. Если вы хотите перерисовать в середине последовательности событий, вам придется разбить ваш скрипт, используя тайм-ауты.

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

edit: вот общая схема для подражания.

function init() { 
    doFirstThing(); 
    updateDisplayForFirstThing(); 
} 

function updateDisplayForFirstThing() {
    // existing code
    ... 

    // prepare next sequence
    var nextFn = function() {
        // does this method run async? if so you'll have to 
        // call updateDisplayForSecondThing as a callback method for the 
        // ajax call rather than calling it inline here.
        doSecondThingWithAjaxCall(); 

        updateDisplayForSecondThing();     
    }

    setTimeout(nextFn, 0);
}

function updateDisplayForSecondThing() {
    // existing code
    ... 

    // prepare next sequence
    var nextFn = function() {
         // continue the pattern 
         // or if you're done call the last method
         reportAllLoaded(); 
    }
    setTimeout(nextFn, 0);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...