JavaScript Одиночный поток
Единственное потоки JavaScript связано с его целью. Как язык сценариев браузера, основная цель JavaScript - взаимодействовать с пользователями и управлять DOM. Это определяет, что он может быть только однопоточным, в противном случае это вызовет очень сложные проблемы синхронизации. Например, предположим, что у JavaScript есть два потока одновременно, один поток добавляет содержимое в определенном узле DOM, а другой поток удаляет этот узел, какой поток должен взять браузер в это время? Следовательно, чтобы избежать сложности, JavaScript - это единственный поток от его рождения, который стал основной особенностью этого языка и не изменится в будущем.
Задачи в очередь
Одиночный потоки означает, что все задачи должны быть в очереди, и предыдущая задача будет выполнена до выполнения следующей задачи. Если предыдущая задача занимает много времени, следующая задача должна ждать.
Асинхронный драйвер событий
Многие поведения в браузере асинхронизированы, такие как: событие щелчка мыши, событие перетаскивания размера окна, событие триггера таймера, обратный вызов xmlhttprequest и т. Д. Когда происходит асинхронное событие, оно входит в очередь событий. В браузере есть внутренний крупный цикл сообщений, цикл событий, который будет опросить большие очереди событий и процессовые события. Например, браузер в настоящее время занимается обработкой события OnClick, а затем происходит другое событие (например, Window On -Size), и это асинхронное событие помещается в очередь событий и ожидает обработки. Это событие будет выполнено только после завершения предыдущей обработки и бесплатно.
Петля мероприятия
JavaScript однопоточный, но браузер не однопоточный
У браузера будет хотя бы некоторые из следующих процессов
1. Рендеринг графического интерфейса браузера
2. Поток двигателя JavaScript
3. Триггерная резьба браузера времена
4. Бружый событие запускает нить нить
5. Браузер http asynchronous запроса потока
Поскольку двигатель JavaScript является однопоточным, код сначала нажимается к очереди, а затем запускается по двигателю первым в первую очередь. Функции обработки событий и функции выполнения таймера также будут размещены в этой очереди, а затем используют бесконечный цикл, чтобы непрерывно извлекать функции из руководителя команды для выполнения. Это цикл событий.
Таким образом, JS однопоточный, но браузер многопоточный. При столкновении с асинхронными вещами браузер поместит асинхронный обратный вызов в цикл событий. Когда поток JS не занят, прочитайте цикл событий.
Принцип таймера
Как использовать таймер
settimeout (fn, задержка)
setInterval (fn, задержка)
FN - это функция или строка, задержка - это время задержки, единица составляет миллисекунды
Есть следующие вещи.
1. Хотя FN может быть строкой, никогда не рекомендуется использовать ее так.
2. Если в FN есть эта функция, это будет указывать на окно при выполнении.
Если вы хорошо понимаете единый поток JS и цикл событий, принцип таймера будет легко понять.
Если установлен таймер, когда время задержки будет достигнуто, браузер поместит событие задержки выполнения в цикл события. Когда время истечет, если поток JS будет простальным, он будет выполнен (так что точность таймера является неточной)
Я прочитал статью о разнице между SetTimeout и SetInterval, которая всегда функционирует. Код выглядит следующим образом
Кода -копия выглядит следующим образом:
settimeout (function () {
SetTimeout (Arguments.Callee, 100)
}, 100)
setInterval (function () {}, 1000)
Общее значение статьи заключается в том, что SetTimeout начинает следующий таймер после выполнения функции обратного вызова, поэтому она должна выполняться с интервалами, в то время как SetInterval выполняется все время. Если вы сталкиваетесь с потоком JS, который продолжает выполнять, вы можете добавить несколько обратных вызовов в цикл событий. Когда поток JS не занят, несколько выполнений будут выполнены один за другим.
После тестирования было обнаружено, что SetInterval находится в определенном интервале, независимо от IE, FF, Chrome, Opera и Safari.
Тестовый код выглядит следующим образом
Кода -копия выглядит следующим образом:
setInterval (function () {
xx.innerhtml = xx.innerhtml+1;
}, 100);
для (var i = 0; i <600000000; i ++) {
xx.offsetwidth
}
settimeout (function () {
отладчик;
}, 10)
Когда точки останова все еще напечатаны только 1
Проблемы точности таймера
Из -за единственного потока JS, если вы столкнетесь с занятостью, таймер определенно будет неточным, и он определенно будет длиннее и длиннее. Это кажется неразрешимым, нет решения.
Другая проблема точности - минимальный интервал -временный разут (развлечение, 0)
Когда поток JS не занят, невозможно выполнить сразу после 0 секунд. Всегда есть минимальный интервал, и каждый браузер все еще отличается. Это не было проверено.
Я прочитал статью о стандарте W3C. Минимальное время выполнения таймера составляет 4 мс. Нет никакого способа проверить источник, если вы не можете его найти! ! !
Некоторые оптимизации, связанные с таймерами
При создании таймеров все еще есть некоторые оптимизации
1. Например, если вы связываете Window.Onrize, триггер будет очень частым при увеличении браузера, так что вы можете отложить выполнение. Когда следующее выполнение будет очищено, оно уменьшит частое выполнение.
Псевдокод заключается в следующем
Кода -копия выглядит следующим образом:
var таймер;
функция r () {
ClearTimeout (таймер);
timer = settimeout (function () {
// что -нибудь делай
}, 150);
}
2. Когда стержень прокрутки стянут, это также немного. Например, ленивая загрузка изображения также должна иметь таймер, чтобы избежать чрезмерных расчетов.
3. Когда есть несколько мест, где необходимы таймеры, вы можете объединить их в таймер. Временный интервал - самый маленький. Затем функция обратного вызова, которую необходимо выполнить, забита в массив. Когда интервал времени достигнут, перечислить через массив для выполнения.
Небольшая демонстрация
Кода -копия выглядит следующим образом:
<! Doctype html>
<html>
<голова>
<meta charset = "utf-8" />
<style>
.wrap {ширина: 80%; Маржа: 30px Auto; Граница: 1PX SOLID #CCC; Заполнение: 20px;}
.c {border: 1px solid #ccc; Высота: 30px; маржиновый блок: 20px;}
</style>
</head>
<тело>
<div id = "xx"> </div>
<div>
<div id = "a1"> 0 </div>
<div id = "a2"> 0 </div>
<div id = "a3"> 0 </div>
<div id = "a4"> 0 </div>
</div>
<script src = "http://static.paipaiimg.com/paipai_h5/js/ttj/zepto.min.js"> </script>
<script type = "text/javascript">
var runtime = {
параметры: {
Шаг: 1000
},
обратные вызовы: [],
AddCallbacks: [],
Начало: ложь,
Таймер: NULL,
extend: function () {
var target = аргументы [0] || {}, i = 1, length = arguments.length, options;
if (typeof target! = "Object" && typeof target! = "function")
target = {};
для (; i <длина; i ++)
if ((options = аргументы [i])! = null)
для (имя var в параметрах) {
var copy = параметры [name];
if (target === Copy)
продолжать;
if (Copy! == не определено)
Target [name] = copy;
}
вернуть цель;
},
init: function (options) {
$ .extend (this, this.options, options || {});
},
добавить: function (веселье, опции) {
параметры = параметры || {};
this.addcallbacks.push ({
Веселье: веселье,
StartTime: New Date (). getTime (),
Шаг: Options.step || this.step,
я: 1
});
var self = это;
if (! this.start) {
this.callbacks = [развлечение];
this.start = true;
this.starttime = new Date (). getTime ();
this.timer = setInterval (function () {
self.done ();
}, this.step);
}
},
выполнено: function () {
Var Callbacks = this.callbacks,
self = это,
newarr = [];
$.
if (obj.step == self.step) {
obj.fun ();
}еще{
if (obj.i == obj.step/self.step) {
if ((новый date (). gettime ())-obj.starttime> obj.step*2/3) {
obj.fun ();
}
obj.i = 1;
}еще{
obj.i = obj.i + 1;
}
}
});
$.
if (obj.step == self.step) {
if ((новый date (). gettime ())-obj.starttime> obj.step*2/3) {
obj.fun ();
Callbacks.push (obj);
}еще{
newarr.push (obj);
}
}еще{
obj.i = obj.i + 1;
Callbacks.push (obj);
}
});
this.addcallbacks = newarr;
},
ясно: function () {
clearInterval (this.timer);
}
}
runtime.init ();
runtime.add (function () {
a1.innerhtml = ~~ a1.innerhtml+1;
});
runtime.add (function () {
a2.innerhtml = ~~ a2.innerhtml+1;
}, {step: 2000});
runtime.add (function () {
a3.innerhtml = ~~ a3.innerhtml+1;
}, {step: 4000});
runtime.add (function () {
a4.innerhtml = ~~ a4.innerhtml+1;
}, {step: 8000});
</script>
</body>
</html>
У вас есть идеи о таймере JavaScript? Оставьте мне сообщение, если у вас есть какие -либо вопросы.