#javascript #jquery
#javascript #jquery
Вопрос:
Для простого проекта я пытаюсь отобразить выходные данные журнала в текстовой области. У меня есть log
функция, и я хотел бы, чтобы текстовая область всегда обновлялась немедленно при каждом log
вызове. К сожалению, кажется, что обновление выполняется только один раз и одновременно загружает все (я использую jQuery для установки значения текстовой области, если это возможно имеет значение). Вот простой пример:
for (i = 0; i <= 100; i ) {
$("textarea").html($("textarea").html() "test" i "n");
$("textarea").scrollTop(9999999)
};
При этом весь текст сразу выводится в текстовую область (примечание: результаты этих примеров вы можете увидеть в этом jsfiddle). Этот базовый пример легко исправить, установив тайм-аут и используя рекурсивные вызовы функций:
f = function(i) {
if (i <= 100) {
$("textarea").html($("textarea").html() "test" i "n");
$("textarea").scrollTop(999999);
setTimeout(function() { f(i 1); }, 0);
}
};
f(1);
Эта версия выдает текст в текстовую область по одной строке за раз, чего я и хочу. Но использование тайм-аутов и обратных вызовов таким образом не представляется практичным при настройке ведения журнала; каждый раз, когда я вызываю log
, мне пришлось бы предоставлять обратный вызов для всех функций, которые я хочу когда-либо выполнять при вызове журнала.
Есть ли какой-либо способ добиться желаемого эффекта без обратных вызовов?
Комментарии:
1. Ну, ваш первый фрагмент настолько быстр, что кажется, что он добавляет текст сразу…
2. Чего именно вы пытаетесь достичь? Чем быстрее компьютер, тем меньше эффект будет заметен в любом случае. Я не совсем понимаю, зачем вам вся эта дополнительная перерисовка.
3. Ребята, я думаю, он хочет иметь возможность «видеть» все сообщения, которые приходят одно за другим (чтобы он мог видеть, что произошло по порядку) .. для этого он должен буферизировать зарегистрированное сообщение и периодически печатать.. смотрите мой ответ
4. Обратите внимание, что, поскольку вы используете тайм-аут, вызов на самом деле не является рекурсивным. 🙂
5. @Felix: В первом фрагменте он не добавляет их все сразу, потому что это быстро; вы можете увидеть, запустив второй фрагмент, что на самом деле отображение одной строки за раз выглядит по-другому. @pimvdb: Приложение представляет собой решатель судоку, который вычисляет список шагов, необходимых для решения судоку, а затем анимирует список шагов позже. Но я хотел бы регистрировать то, что происходит в решателе, по мере его вычисления. Кроме того, если решатель когда-либо выйдет из строя, в текстовую область ничего не выводится, что определенно является проблемой. @dwarfy: спасибо, это выглядит как отличное решение.
Ответ №1:
Я думаю, вы могли бы рассмотреть возможность использования :
$("textarea").val(function(index, value) {
return value "test" i "n"
});
вместо :
$("textarea").html($("textarea").html() "test" i "n");
или вообще :
$("textarea").val(NEWVAL)
Также отмечено в комментариях к вашему вопросу, если вы хотите иметь возможность замечать «на глаз» все поступающие сообщения, вам придется сохранять их в буфере и иметь что-то вроде (не тестировалось) :
var buffer = []
function log(text) { buffer.push(text) }
setInterval(function(){
if (len(buffer)>0) {
$("textarea").val(function(index, value) {
return value "n" buffer.shift()
});
}
},500)
Ответ №2:
Браузеры обычно (Opera является исключением) выполняют выполнение JS и рендеринг в одном потоке, поэтому, пока ваш JS запущен, рендеринг в браузере выполняться не будет, если вы явно не передадите управление с помощью тайм-аута или интервального таймера.