Существуют ли какие-либо атомные javascript-операции для работы с асинхронной природой Ajax?
Я динамически загружаю код (функции) с сервера и выполняю его как код javascript, а затем сохраняю его в массиве и выполняю. Все эти фрагменты кода должны выполняться ровно один раз. Psuedocode следует как таковой
function fetch(foo){
if (foo in fooArray){
//Do Nothing
else{
//Fetch foo via Ajax and execute foo()
}
}
Проблема значительно сложнее, но по существу, если я выдаю команду ниже
fetch('someFunctionName');
fetch('someFunctionName');
fetch('someFunctionName');
fetch('someFunctionName');
все четыре будут исполнять if (foo in fooArray)
и предположить, что он не находится в массиве, и все четыре будут приступать к извлечению кода и его выполнению. Я помню, как в тот же день я узнал о семафорах и мьютексах, есть ли такие вещи для javascript.
Ответы
Ответ 1
JavaScript - хороший язык, который отлично работает с асинхронными обратными вызовами, тайм-аутами, интервалами и пользовательскими событиями, но не имея проблем с concurrency. Это возможно, потому что JavaScript по сути однопоточен - данный кусок кода всегда выполняется атомарно и никогда не прерывается другим потоком, выполняющим JavaScript.
Ваша функция fetch()
всегда будет выполняться без прерывания. Если он выполняется как часть обратного вызова AJAX и если несколько обратных вызовов AJAX находятся на ожидании, они будут поставлены в очередь.
Другой пример: если у вас есть обработчик событий, назначенный входному элементу, и вы запускаете событие несколько раз подряд, обработчики событий не будут выполняться одновременно. Вместо этого они будут поставлены в очередь и выполняться последовательно. Это также относится к нескольким событиям, вызванным setTimeout()
/setInterval()
.
В качестве примечания: это одна из причин, почему node.js является настолько надежным: он использует только один поток и никогда не блокирует операции ввода /O, но использует обратные вызовы, когда данные готовы/событие происходит.
Ответ 2
Javascript по существу однопоточный, поэтому вам не нужен мьютекс. Ваша выборка могла бы установить флаги так, чтобы последующие вызовы выборки могли избежать вызова ajax, например:
var beingFetched = {};//map onflight -> callbacks
function fetch(foo){
if (foo in fooArray){
//Do Nothing
} else {
if (beingFetched.foo) { //note empty array is truthy
//register a callback
var callback = function(r){
//anything you need to do wit the return object r
//maybe even eval it.
};
//the callback would more likely be an argument to fetch itself
//or you could use a promise API instead so that you can at your will
//register multiple callbacks - for error, for success etc.
beingFetched.foo.push(callback);
} else {
beingFetched.foo = [];//truthy
//Fetch foo via Ajax and execute
$.ajax("getFoo/"+foo).done(function() {
_.each(beingFetched.foo, function(cb){
cb.apply(cb,arguments);
});
delete beingFetched.foo;
});
}
}
}