我从服务器动态加载代码(函数)并将其作为javascript代码执行,然后将其存储在数组中并执行。所有这些代码片段必须只执行一次。伪造的代码如下:
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这样的东西。
答案 0 :(得分:33)
JavaScript是一种很好的语言,可以很好地处理异步回调,超时,间隔和用户事件,但没有任何并发问题。这是可能的,因为JavaScript基本上是单线程的 - 给定的代码片段总是以原子方式执行,并且不会被另一个运行JavaScript的线程中断。
您的fetch()
功能将始终执行而不会中断。如果它作为AJAX回调的一部分执行,并且如果多个AJAX回调处于挂起状态,它们将排队。
另一个示例:如果您将一个事件处理程序分配给一个输入元素,并且您一次多次触发该事件,则不会同时执行事件处理程序。相反,它们将按顺序排队并执行。这也适用于setTimeout()
/ setInterval()
触发的多个事件。
作为旁注:这是node.js如此强大的原因之一:它只使用单个线程而且从不在I / O上阻塞,而是在数据准备就绪/事件发生时使用回调。 / p>
答案 1 :(得分:1)
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;
});
}
}
}