Может Javascript Ajax привести к взаимоблокировкам?

У меня есть мысленный эксперимент. В моем коде у меня есть глобальная переменная say var changeMe;, и я делаю несколько вызовов Ajax.

 //call One -- third param is the callback function
    ajaxFunction(url1, params,function(data){
        changeMe = data;
    });

//call Two
    ajaxFunction(url2, params,function(data){
        changeMe = data;
    });

Значит, значение changeMe будет зависеть от того, какой вызов Ajax заканчивается последним, что означает, что завершающий последний вызов перезапишет это значение.

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

Поскольку Javascript является однопоточным, мы обычно не будем получать эту проблему, но это может возникнуть в случае вызовов setTimeout и Ajax. Я не знаю, как я могу точно реплицировать эту проблему, поэтому она по-прежнему остается мысленным экспериментом.

Итак, как в многопоточных условиях работает тупик?

Я предпочитаю, чтобы ответ вроде changeMe был url1 или url2, и ясное объяснение ситуации..

Заранее спасибо

Ответ 1

Javascript имеет очередь событий. Это означает, что он обрабатывает ВСЕ события (события, инициируемые пользователем, события setTimeout, ajax возвращает события) один за другим, так как они приходят.

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

function processURLs() {
    var url1 = "http://www.url1.com/";
    var url2 = "http://www.url2.com/";
    var data1 = null;
    var data2 = null;

    ajaxFunction(url1, params, function(data){
        data1 = data;
        if( data2 !== null ) {
            process(data1, data2);
        }
    });

    ajaxFunction(url2, params, function(data){
        data2 = data;
        if( data1 !== null ) {
            process(data1, data2);
        } 
    });
}

Вы сказали, что javascript является однопоточным. Это так. Этот поток продолжает цикл и выдает события из этой очереди, когда происходят события для обработки.

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

Если вы хотите знать , как работает javascript-таймер с этой очередью событий, я настоятельно рекомендую прочитать John Resig сообщение в блоге об этом

Если вам нужна дополнительная информация о о том, как сетевые события передаются в ваш браузер (javascript), вы должны узнать о Модель OSI.

Например, ваш браузер находится в слое OSI 7 (Application), но порядок сетевых событий будет определен ниже (уровни с 3 по 6).

Итак, подытожим ответ: никто не может сказать вам, что changeMe будет url1 или url2. Javascript не будет определять порядок здесь, он будет решен в более глубоких слоях (ваша сетевая карта, ваша операционная система и т.д.).

Ответ 2

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

Если две асинхронные операции завершаются в одно и то же время, оба будут сигнализировать об их завершении одновременно, а затем планировщик Javascript выберет один из двух обратных вызовов для запуска в первую очередь.

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