Является ли JavaScript многопоточным? - PullRequest
54 голосов
/ 02 ноября 2009

Вот моя проблема - мне нужно динамически загрузить несколько сценариев с помощью jQuery.getScript () и выполнить определенный код JavaScript после загрузки всех сценариев, поэтому я планировал сделать что-то вроде этого:

function GetScripts(scripts, callback)
{
  var len = scripts.length
  for (var i in scripts)
  {
    jQuery.getScript(scripts[i], function() 
    {
      len --;
      // executing callback function if this is the last script that loaded
      if (len == 0)
        callback()  
    })
  }
}

Это будет работать надежно только в том случае, если мы предположим, что события script.onload для каждого сценария запускаются и выполняются последовательно и синхронно, поэтому никогда не возникнет ситуация, когда два или более обработчика событий пройдут проверку на наличие (len == 0 ) и выполнить метод обратного вызова.

Итак, мой вопрос - правильно ли это предположение, и если нет, то каким образом добиться того, что я пытаюсь сделать?

Ответы [ 9 ]

80 голосов
/ 02 ноября 2009

Нет, JavaScript не многопоточный. Это зависит от событий, и вы увидите, что вы предполагаете, что события запускаются последовательно (если они загружаются последовательно). Ваша текущая реализация кажется правильной. Я считаю, что jQuery .getScript() внедряет новый тег <script>, который также должен заставить их загружаться в правильном порядке.

34 голосов
/ 02 ноября 2009

В настоящее время JavaScript не является многопоточным, но в ближайшем будущем ситуация изменится. В HTML5 появилась новая вещь , которая называется Worker . Это позволяет вам выполнять некоторую работу в фоновом режиме.

Но в настоящее время он поддерживается не всеми браузерами.

16 голосов
/ 02 ноября 2009

В спецификации JavaScript (ECMAScript) не определены механизмы потоков или синхронизации.

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

В качестве идентификатора другой комментатор ссылается на тот факт, что любой поставщик JavaScriptengine может добавить функции потоков и синхронизации, или поставщик может позволить пользователям реализовать эти функции самостоятельно, как описано в этой статье: Многопоточный JavaScript ?

12 голосов
/ 02 ноября 2009

JavaScript абсолютно не многопоточный - у вас есть гарантия, что любой используемый вами обработчик не будет прерван другим событием. Любые другие события, такие как щелчки мышью, XMLHttpRequest, возвращаются, а таймеры помещаются в очередь во время выполнения вашего кода и запускаются одно за другим.

10 голосов
/ 02 ноября 2009

Нет, все браузеры предоставляют вам только один поток для JavaScript.

3 голосов
/ 11 ноября 2014

Для ясности, реализация JS в браузере - это , а не многопоточная .

Язык , JS, может быть многопоточным .

Однако этот вопрос здесь не применяется.

Что применимо, так это то, что getScript () является асинхронным (возвращает немедленно и получает в очередь), однако браузер будет последовательно выполнять содержимое, подключенное к DOM <script>, поэтому ваш зависимый код JS будет видеть их загруженными последовательно. Это функция браузера, которая не зависит от потоков JS или вызова getScript ().

Если getScript () извлекает сценарии с помощью xmlHTTPRequest, setTimeout (), websockets или любого другого асинхронного вызова, то ваши сценарии не будут гарантированно выполняться по порядку. Однако ваш обратный вызов будет по-прежнему вызываться после выполнения всех сценариев, поскольку контекст выполнения вашей переменной 'len' находится в замыкании, которое сохраняет свой контекст посредством асинхронных вызовов вашей функции.

1 голос
/ 03 ноября 2009

Думаю, было бы интересно попробовать это с задержкой доставки скрипта " принудительно " ...

  1. добавлены два доступных скрипта из Google
  2. добавлено delayjs.php в качестве 2-го элемент массива. delayjs.php спит в течение 5 секунд, прежде чем доставить пустой JS объект.
  3. добавил обратный вызов, который « проверяет » существование ожидаемые объекты из скрипта файлы.
  4. добавлено несколько команд js, которые выполняются на линии после Вызов GetScripts () для последовательных js-команд " test ".

Результат с загрузкой скрипта соответствует ожидаемому; обратный вызов срабатывает только после загрузки последнего скрипта. Что меня удивило, так это то, что команды js, следующие за вызовом GetScripts (), сработали без необходимости ждать загрузки последнего скрипта. У меня сложилось впечатление, что никакие команды js не будут выполняться, пока браузер ожидает загрузки сценария js ...

var scripts = [];
scripts.push('http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js');
scripts.push('http://localhost/delayjs.php');
scripts.push('http://ajax.googleapis.com/ajax/libs/scriptaculous/1.8.3/scriptaculous.js');


function logem() {
    console.log(typeof Prototype);
    console.log(typeof Scriptaculous);
    console.log(typeof delayedjs);
}

GetScripts( scripts, logem );

console.log('Try to do something before GetScripts finishes.\n');
$('#testdiv').text('test content');

<?php

sleep(5);
echo 'var delayedjs = {};';
0 голосов
/ 05 октября 2015

JS в целом однопоточный. Однако веб-работники HTML5 вводят многопоточность. Узнайте больше на http://www.html5rocks.com/en/tutorials/workers/basics/

0 голосов
/ 02 сентября 2011

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

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