Когда JavaScript синхронно?

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

Ответ 1

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

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

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

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

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

Ответ 2

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 всегда синхронный.

Ответ 3

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

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

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

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

async

Ответ 4

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

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

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

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

Я надеюсь, что это достаточно ясно, чтобы быть полезным для кого-то.

Ответ 5

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

Ответ 6

лол! DEMO 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>