JavaScript и темы

Есть ли способ сделать многопоточность в JavaScript?

Ответ 1

См. http://caniuse.com/#search=worker для получения самой последней информации о поддержке.

Ниже приводится состояние поддержки около 2009 года.


Слова, которые вы хотите использовать для google для Рабочие темы JavaScript

Помимо Gears там ничего не доступно прямо сейчас, но есть много разговоров о том, как реализовать это, поэтому я думаю, посмотрю этот вопрос так как ответ, несомненно, изменится в будущем.

Здесь соответствующая документация для Gears: API WorkerPool

WHATWG имеет проект рекомендации для рабочих потоков: Веб-работники

И там также Mozillas Рабочие темы DOM


Обновление: Июнь 2009, текущее состояние поддержки браузера для потоков JavaScript

Firefox 3.5 имеет веб-работников. Некоторые демонстрации веб-работников, если вы хотите увидеть их в действии:

Плагин Gears также может быть установлен в Firefox.

Safari 4, а WebKit nightlies - рабочие потоки:

Chrome использует Gears, поэтому он может создавать потоки, хотя для него требуется запрос подтверждения от пользователя (и он использует другой API для веб-работников, хотя он будет работать в любом браузере с установлен плагин Gears):

  • Google Gears WorkerPool Demo (не очень хороший пример, поскольку он работает слишком быстро, чтобы протестировать в Chrome и Firefox, хотя IE работает достаточно медленно, чтобы см. блокирование взаимодействия)

IE8 и IE9 могут работать только потоки с установленным плагином Gears

Ответ 2

Различные способы выполнения многопоточных и асинхронных в JavaScript

До HTML5 JavaScript разрешил выполнение только одного потока на странице.

Был некоторый хакерский способ моделирования асинхронного выполнения с Yield, setTimeout(), setInterval(), XMLHttpRequest или обработчиками событий (см. конец этого сообщения для примера с yield и setTimeout()).

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


Реальная многопоточность

Многопоточность: Рабочие темы JavaScript

В HTML5 представлены темы веб-рабочих (см. совместимость браузеров)
Примечание. IE9 и более ранние версии не поддерживают его.

Эти рабочие потоки представляют собой потоки JavaScript, которые запускаются в фоновом режиме, не влияя на производительность страницы. Для получения дополнительной информации о Работодателе прочитать документацию или этот учебник.

Вот простой пример с тремя потоками Web Worker, которые считаются MAX_VALUE и отображают текущее вычисленное значение на нашей странице:

//As a worker normally take another JavaScript file to execute we convert the function in an URL: http://stackoverflow.com/a/16799132/2576706
function getScriptPath(foo){ return window.URL.createObjectURL(new Blob([foo.toString().match(/^\s*function\s*\(\s*\)\s*\{(([\s\S](?!\}$))*[\s\S])/)[1]],{type:'text/javascript'})); }

var MAX_VALUE = 10000;

/*
 *	Here are the workers
 */
//Worker 1
var worker1 = new Worker(getScriptPath(function(){
    self.addEventListener('message', function(e) {
        var value = 0;
        while(value <= e.data){
            self.postMessage(value);
            value++;
        }
    }, false);
}));
//We add a listener to the worker to get the response and show it in the page
worker1.addEventListener('message', function(e) {
  document.getElementById("result1").innerHTML = e.data;
}, false);


//Worker 2
var worker2 = new Worker(getScriptPath(function(){
    self.addEventListener('message', function(e) {
        var value = 0;
        while(value <= e.data){
            self.postMessage(value);
            value++;
        }
    }, false);
}));
worker2.addEventListener('message', function(e) {
  document.getElementById("result2").innerHTML = e.data;
}, false);


//Worker 3
var worker3 = new Worker(getScriptPath(function(){
    self.addEventListener('message', function(e) {
        var value = 0;
        while(value <= e.data){
            self.postMessage(value);
            value++;
        }
    }, false);
}));
worker3.addEventListener('message', function(e) {
    document.getElementById("result3").innerHTML = e.data;
}, false);


// Start and send data to our worker.
worker1.postMessage(MAX_VALUE); 
worker2.postMessage(MAX_VALUE); 
worker3.postMessage(MAX_VALUE);
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>

Ответ 3

С боковыми спецификациями HTML5 не нужно больше взломать javascript с помощью setTimeout(), setInterval() и т.д.

HTML5 и Друзья вводят спецификацию javascript Веб-рабочие. Это API для запуска скриптов асинхронно и независимо.

Ссылки на спецификация и tutorial.

Ответ 4

В JavaScript нет истинных потоков. JavaScript, являющийся податливым языком, который он есть, позволяет вам эмулировать некоторые из них. Вот пример с которым я столкнулся на днях.

Ответ 5

В Javascript нет истинной многопоточности, но вы можете получить асинхронное поведение с помощью setTimeout() и асинхронных запросов AJAX.

Что именно вы пытаетесь выполнить?

Ответ 6

Вот только способ моделировать многопоточность в Javascript

Теперь я собираюсь создать 3 потока, которые будут вычислять добавление чисел, числа можно разделить на 13, а числа можно разделить на 3 до 10000000000. И эти 3 функции не могут работать в то же время, что и Concurrency означает. Но я покажу вам трюк, который заставит эти функции работать рекурсивно в одно и то же время: jsFiddle

Этот код принадлежит мне.

Часть тела

    <div class="div1">
    <input type="button" value="start/stop" onclick="_thread1.control ? _thread1.stop() : _thread1.start();" /><span>Counting summation of numbers till 10000000000</span> = <span id="1">0</span>
</div>
<div class="div2">
    <input type="button" value="start/stop" onclick="_thread2.control ? _thread2.stop() : _thread2.start();" /><span>Counting numbers can be divided with 13 till 10000000000</span> = <span id="2">0</span>
</div>
<div class="div3">
    <input type="button" value="start/stop" onclick="_thread3.control ? _thread3.stop() : _thread3.start();" /><span>Counting numbers can be divided with 3 till 10000000000</span> = <span id="3">0</span>
</div>

Часть Javascript

var _thread1 = {//This is my thread as object
    control: false,//this is my control that will be used for start stop
    value: 0, //stores my result
    current: 0, //stores current number
    func: function () {   //this is my func that will run
        if (this.control) {      // checking for control to run
            if (this.current < 10000000000) {
                this.value += this.current;   
                document.getElementById("1").innerHTML = this.value;
                this.current++;
            }
        }
        setTimeout(function () {  // And here is the trick! setTimeout is a king that will help us simulate threading in javascript
            _thread1.func();    //You cannot use this.func() just try to call with your object name
        }, 0);
    },
    start: function () {
        this.control = true;   //start function
    },
    stop: function () {
        this.control = false;    //stop function
    },
    init: function () {
        setTimeout(function () {
            _thread1.func();    // the first call of our thread
        }, 0)
    }
};
var _thread2 = {
    control: false,
    value: 0,
    current: 0,
    func: function () {
        if (this.control) {
            if (this.current % 13 == 0) {
                this.value++;
            }
            this.current++;
            document.getElementById("2").innerHTML = this.value;
        }
        setTimeout(function () {
            _thread2.func();
        }, 0);
    },
    start: function () {
        this.control = true;
    },
    stop: function () {
        this.control = false;
    },
    init: function () {
        setTimeout(function () {
            _thread2.func();
        }, 0)
    }
};
var _thread3 = {
    control: false,
    value: 0,
    current: 0,
    func: function () {
        if (this.control) {
            if (this.current % 3 == 0) {
                this.value++;
            }
            this.current++;
            document.getElementById("3").innerHTML = this.value;
        }
        setTimeout(function () {
            _thread3.func();
        }, 0);
    },
    start: function () {
        this.control = true;
    },
    stop: function () {
        this.control = false;
    },
    init: function () {
        setTimeout(function () {
            _thread3.func();
        }, 0)
    }
};

_thread1.init();
_thread2.init();
_thread3.init();

Я надеюсь, что этот способ будет полезен.

Ответ 7

Вы можете использовать описательный JavaScript, компилятор, который преобразует ваш код в конечный автомат, эффективно позволяя вам эмулировать потоки. Это делается путем добавления оператора "yielding" (обозначенного как "- > " ) на языке, который позволяет вам писать асинхронный код в одном линейном блоке кода.

Ответ 8

Новый движок v8, который должен выйти, сегодня поддерживает его (я думаю)

Ответ 9

Другим возможным методом является использование javascript-интерпретатора в среде javascript.

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

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

Я сделал небольшой проект продемонстрировать это.

Более подробное объяснение в этом сообщении в блоге.

Ответ 10

В сыром Javascript лучшее, что вы можете сделать, это использовать несколько асинхронных вызовов (xmlhttprequest), но это не очень многопоточное и очень ограниченное. Google Gears добавляет в браузер несколько API-интерфейсов, некоторые из которых могут использоваться для поддержки потоков.

Ответ 11

Если вы не можете или не хотите использовать какой-либо материал AJAX, используйте iframe или десять!;) У вас могут быть процессы, запущенные в iframe, параллельно с главной страницей, не беспокоясь о сопоставимых проблемах с перекрестным браузером или проблемах с синтаксисом с dot net AJAX и т.д., И вы можете вызвать главную страницу JavaScript (включая импортированный JavaScript) из IFrame.

Например, в родительском iframe вызывать egFunction() в родительском документе после загрузки содержимого iframe (это асинхронная часть)

parent.egFunction();

Динамически сгенерировать iframes так, чтобы основной html-код был свободен от них, если вы хотите.

Ответ 12

Javascript не имеет потоков, но у нас есть рабочие.

Рабочие могут быть хорошим выбором, если вам не нужны общие объекты.

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

Я разработал библиотеку под названием task.js, которая делает это очень легко.

task.js Упрощенный интерфейс для запуска кода интенсивной работы процессора на всех ядрах (node.js, и веб)

Пример:

function blocking (exampleArgument) {
    // block thread
}

// turn blocking pure function into a worker task
const blockingAsync = task.wrap(blocking);

// run task on a autoscaling worker pool
blockingAsync('exampleArgumentValue').then(result => {
    // do something with result
});

Ответ 13

С HTML5 спецификация вам не нужно писать слишком много JS для того же или найти некоторые хаки.

Одной из функций, введенных в HTML5, является Web Workers, который работает в фоновом режиме, независимо от других скриптов, не влияя на производительность страницы.

Поддерживается почти во всех браузерах:

Chrome - 4.0+

IE - 10.0 +

Mozilla - 3.5 +

Safari - 4.0 +

Opera - 11.5 +