Когда JavaScript является синхронным? - PullRequest
170 голосов
/ 10 января 2010

У меня сложилось впечатление, что JavaScript всегда был асинхронным. Тем не менее, я узнал, что есть ситуации, когда это не так (например, манипуляции с DOM). Есть ли хорошая ссылка где-нибудь о том, когда он будет синхронным и когда он будет асинхронным? Влияет ли на это jQuery?

Ответы [ 6 ]

240 голосов
/ 10 января 2010

JavaScript всегда синхронный и однопоточный. Если вы выполняете блок кода JavaScript на странице, то никакой другой код JavaScript на этой странице в настоящее время не будет выполняться.

JavaScript является только асинхронным в том смысле, что он может выполнять, например, вызовы Ajax. Вызов Ajax прекратит выполнение, и другой код сможет выполняться до тех пор, пока вызов не завершится (успешно или нет), после чего обратный вызов будет выполняться синхронно. Никакой другой код не будет запущен в этот момент. Он не будет прерывать любой другой код, который в данный момент выполняется.

Таймеры JavaScript работают с таким же типом обратного вызова.

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

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

175 голосов
/ 08 сентября 2015

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

Контекст выполнения

Механизм JavaScript взаимодействует с другими механизмами в браузере. В стеке выполнения JavaScript есть глобальный контекст внизу, а затем, когда мы вызываем функции, механизм JavaScript создает новые контексты выполнения для соответствующих функций. Когда вызываемая функция выходит, ее контекст выполнения извлекается из стека, а затем извлекается следующий контекст выполнения и так далее ...

Например

function abc()
{
   console.log('abc');
}


function xyz()
{
   abc()
   console.log('xyz');
}
var one = 1;
xyz();

В приведенном выше коде будет создан глобальный контекст выполнения, и в этом контексте var one будет сохранен, и его значение будет равно 1 ... при вызове xyz (), тогда будет создан новый контекст выполнения и если бы мы определили любую переменную в функции xyz, эти переменные были бы сохранены в контексте выполнения xyz (). В функции xyz мы вызываем abc (), а затем создается контекст выполнения abc () и помещается в стек выполнения ... Теперь, когда abc () завершает, его контекст извлекается из стека, затем контекст xyz () извлекается из стек и тогда глобальный контекст будет вытолкнут ...

Теперь об асинхронных обратных вызовах; асинхронный означает более одного за один раз.

Так же, как и стек выполнения, существует Очередь событий . Когда мы хотим получить уведомление о каком-либо событии в движке JavaScript, мы можем прослушать это событие, и это событие помещается в очередь. Например, событие запроса Ajax или событие запроса HTTP.

Всякий раз, когда стек выполнения пуст, как показано в приведенном выше примере кода, механизм JavaScript периодически просматривает очередь событий и определяет, есть ли какое-либо событие, о котором следует уведомить. Например, в очереди было два события: запрос ajax и запрос HTTP. Он также проверяет, есть ли функция, которая должна быть запущена для этого триггера события ... Таким образом, механизм JavaScript уведомляется о событии и знает соответствующую функцию для выполнения в этом событии ... Таким образом, механизм JavaScript вызывает функция-обработчик, в примере, например, AjaxHandler () будет вызываться и, как всегда, когда вызывается функция, ее контекст выполнения помещается в контекст выполнения, и теперь выполнение функции завершается, а запрос ajax события также удаляется из очереди событий ... Когда AjaxHandler () завершает стек выполнения пуст, поэтому механизм снова просматривает очередь событий и запускает функцию обработчика событий HTTP-запроса, который был следующим в очереди. Важно помнить, что очередь событий обрабатывается только тогда, когда стек выполнения пуст.

Например, см. Код ниже, объясняющий стек выполнения и обработку очереди событий движком Javascript.

function waitfunction() {
    var a = 5000 + new Date().getTime();
    while (new Date() < a){}
    console.log('waitfunction() context will be popped after this line');
}

function clickHandler() {
    console.log('click event handler...');   
}

document.addEventListener('click', clickHandler);


waitfunction(); //a new context for this function is created and placed on the execution stack
console.log('global context will be popped after this line');

И

<html>
    <head>

    </head>
    <body>

        <script src="program.js"></script>
    </body>
</html>

Теперь запустите веб-страницу и нажмите на страницу, и увидите вывод на консоли. Выход будет

waitfunction() context will be popped after this line
global context will be emptied after this line
click event handler...

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

Так что JavaScript всегда синхронен.

95 голосов
/ 10 января 2010

JavaScript является однопоточным, и все время вы работаете над нормальным синхронным выполнением потока кода.

Хорошими примерами асинхронного поведения, которое может иметь JavaScript, являются события (взаимодействие с пользователем, результаты запроса Ajax и т. Д.) И таймеры, в основном действия, которые могут произойти в любое время.

Я бы порекомендовал вам взглянуть на следующую статью:

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

async

2 голосов
/ 01 ноября 2018

Для тех, кто действительно понимает, как работает JS, этот вопрос может показаться странным, однако большинство людей, использующих JS, не имеют такого глубокого понимания (и не обязательно в этом), и для них это довольно запутанный вопрос Я постараюсь ответить с этой точки зрения.

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

Основная путаница возникает из-за того, что ваш браузер может сказать JS, чтобы он извинял больше кода в любое время (аналогично тому, как вы можете извинить больше кода JS на странице из консоли). Например, в JS есть функции обратного вызова, цель которых состоит в том, чтобы позволить JS вести себя асинхронно, чтобы дальнейшие части JS могли работать, ожидая, пока выполненная функция JS (вызов IE 100 *) вернет ответ, JS продолжит работу. запускаться до тех пор, пока браузер не получит ответ, и цикл обработки событий (браузер) выполнит код JS, который вызывает функцию обратного вызова.

Поскольку цикл обработки событий (браузер) может вводить больше JS для выполнения в любой точке, в этом смысле JS является асинхронным (основными причинами, по которым браузер вводит код JS, являются тайм-ауты, обратные вызовы и события)

Надеюсь, это достаточно ясно, чтобы кому-то помочь.

0 голосов
/ 13 июня 2019

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

console.log("1");
function taketime(){
   for(var i=0;i<1000000;i++){ if(i==1000000) console.log(i);}
}
taketime();
console.log("2");

Сначала будет напечатано «1», основной поток блокируется, пока не будет выполнена функция taketime (), а в конце будет напечатано «2».

Если бы JS был асинхронным, то вывод был бы

1
2
10000000
0 голосов
/ 11 мая 2019

лол! ДЕМО https://jsfiddle.net/9vs1gbtq/ Для этого подтверждения: «JavaScript всегда является синхронным и однопоточным. Если вы выполняете блок кода JavaScript на странице, то никакой другой JavaScript на этой странице в настоящее время не будет выполняться».

мой ответ:

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus,the best editor in the World">
  <title>jQuery interval plug-in</title>
  <style type="text/css">
    p{font-size:24px;color:red}
  </style>
 </head>
 <body>
<p id="thread0">0</p><p id="thread1">0</p>
<p id="thread2">0</p><p id="thread3">0</p>
<p id="thread4">0</p><p id="thread5">0</p>
<p id="thread6">0</p><p id="thread7">0</p>
<p id="thread8">0</p><p id="thread9">0</p>

 <!-- these are multiple choises to jquery or zepto (local or from cdns) -->

<!-- 
i am using these in xampp ,under windows server:

<script src="../js/zepto.min.js"></script>
 <script src="../js/jquery.js"></script>  

-->


<!-- 
<script src="https://code.jquery.com/jquery-3.4.0.min.js"></script>
<script src="https://code.jquery.com/jquery-3.4.0.js"></script>
<script src="https://code.jquery.com/jquery-3.4.0.slim.js"></script>
<script src="https://code.jquery.com/jquery-3.4.0.slim.min.js"></script>
-->


<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<!-- (Zepto.js is the equivalent of jQuery,but faster ,created by  genious :
               thanx Thomas Fuchs and contributors!!!
) -->

<!--
<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.js"></script>
 -->



 <!-- 


 -->


<script>
//THIS IS MY PLUGIN ON https://github.com/xpectmore/jQuery-Interval
    //start plug-in
jqzp=function(){console.log('jQuery/Zepto not found: please enable one of them!');}
if (typeof($) == 'undefined'){  jqzp(); }else $( document ).ready(function(){
    var _sI=[];
    $.interval=function(){
        if (arguments.length==3){
            if (_sI[arguments[0]]== undefined){
                _sI[arguments[0]]={};
            }else{
                clearInterval(_sI[arguments[0]].reg);
            }
            _sI[arguments[0]].fn=arguments[2];
            _sI[arguments[0]].t=arguments[1];
            _sI[arguments[0]].reg=setInterval(arguments[2],arguments[1]);
        }else if (arguments.length==1){
            clearInterval(_sI[arguments[0]].reg);
        }else{
            console.log('The number of the arguments should be 3 or 1');
            console.log('$.interval("id",time_in_milliseconds,function(){do_what_you_want();})');
            console.log('to stop that use: $.interval("id")');
        }
    }
});
//stop plug-in
</script>



<script>


$( document ).ready(function(){


    var th0=0;
    $.interval('th0',500,function(){
        $('#thread0').text(th0);
        th0++;
    });
    var th1=0;
    $.interval('th1',1000,function(){
        $('#thread1').text(th1);
        th1++;
    });
    var th2=0;
    $.interval('th2',1500,function(){
        $('#thread2').text(th2);
        th2++;
    });
    var th3=0;
    $.interval('th3',500,function(){
        $('#thread3').text(th3);
        th3++;
    });
    var th4=0;
    $.interval('th4',1000,function(){
        $('#thread4').text(th4);
        th4++;
    });
    var th5=0;
    $.interval('th5',1500,function(){
        $('#thread5').text(th5);
        th5++;
    });
    var th6=0;
    $.interval('th6',500,function(){
        $('#thread6').text(th6);
        th6++;
    });
    var th7=0;
    $.interval('th7',1000,function(){
        $('#thread7').text(th7);
        th7++;
    });
    var th8=0;
    $.interval('th8',1500,function(){
        $('#thread8').text(th8);
        th8++;
    });
    var th9=0;
    $.interval('th9',500,function(){
        $('#thread9').text(th9);
        th9++;
    });

});


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