我想知道何时存在一个在JavaScript代码中执行同步的解决方案。例如,我有以下情况:我正在尝试从AJAX调用缓存一些响应值,问题是,它可以同时执行多次调用,因此它会导致代码中的竞争条件。所以我很好奇为此寻找解决方案?谁有想法要做?
答案 0 :(得分:8)
我可以提供一个可能的解决方案,但是没有看到代码......不完全确定你在做什么,但没有理由不能这样做。
jQuery中的基本代码:(未经测试和缩写......但我做过类似的事情)
var needAllThese = {};
$(function(){
$.ajax("POST","/somepage.aspx",function(data) {
needAllThese.A = "VALUE";
});
$.ajax("POST","/somepage2.aspx",function(data) {
needAllThese.B = "VALUE";
});
$.ajax("POST","/somepage3.aspx",function(data) {
needAllThese.C = "VALUE";
});
startWatching();
});
function startWatching() {
if (!haveEverythingNeeded()) {
setTimeout(startWatching,100);
return;
}
everythingIsLoaded();
}
function haveEverythingNeeded() {
return needAllThese.A && needAllThese.B && needAllThese.C;
}
function everythingIsLoaded() {
alert("Everything is loaded!");
}
编辑:(重新:你的评论)
你正在寻找回调,就像jQuery一样。
var cache = {};
function getSomeValue(key, callback) {
if (cache[key]) callback( cache[key] );
$.post( "url", function(data) {
setSomeValue(key,data);
callback( cache[key] );
});
}
function setSomeValue(key,val) {
cache[key] = val;
}
$(function(){
// not sure you would need this, given the code above
for ( var i = 0; i < some_length; ++i) {
$.post( "url", function(data){
setSomeValue("somekey",data);
});
}
getSomeValue("somekey",function(val){
$("#element").txt( val );
};
});
答案 1 :(得分:6)
Javascript本质上是单线程的,至少对于普通的浏览器环境而言。永远不会有两个同时执行访问同一文档的脚本。 (新的Javascript工作线程在这里可能是一个例外,但它们根本不是为了访问文档,只是为了通过消息传递进行通信)。
答案 2 :(得分:4)
我找到了解决问题的方法。我不得不说它并不像我想要的那样完美,但到目前为止它的确有效,我认为这更像是暂时的解决方法。
$.post( "url1", function( data)
{
// do some computation on data and then
setSomeValue( data);
});
var setSomeValue = ( function()
{
var cache = {};
return function( data)
{
if ( cache[data] == "updating")
{
setTimeout( function(){ setSomeValue( data);}, 100);
return;
}
if ( !cache[date])
{
cache[date] = updating;
$.post( "url2", function( another_data)
{
//make heavy computation on another_data
cache[data] = value;
// update the UI with value
});
}
else
{
//update the UI using cached value
}
}
})();
答案 3 :(得分:3)
是的,你可以让你的xmlHttpRequests同步,在非IE中使用bAsync参数在IE浏览器asynch option中将open do the same设置为false。
也许您可能想以某种方式链接您的请求。创建一个que堆栈,并在你向下走的路上发送请求。
答案 4 :(得分:3)
首先,重要的是要知道所有当前的JS实现都是单线程的,因此我们不讨论竞争条件并在通常使用的上下文中进行同步。
作为旁注,浏览器现在引入了工作线程,这将允许JS中的并发性,但目前情况并非如此。
无论如何,您仍然面临着期望通过异步调用收到哪些数据的问题,而您无法保证收到订单的顺序。
JS通过回调为您提供了一个非常好的解决方案。对于您将要发送的每个异步事件,将一个适当的回调函数附加到它,它将正确处理事件。按照你的意思,同步应该在那里发生。
答案 5 :(得分:1)
我知道这是后来的事,但我想我会改进。 Artem Barger制定了自己的解决方案,如果缓存的值为&#34;更新&#34; ...而只是将函数标记到一个链接队列中,对着缓存的值,这样你就有了一个对象,它保存了实际的缓存数据,以及在返回数据后用缓存数据调用的函数队列。
所以,如果它是&#34;更新&#34;只需将您的函数添加到与项目数据链接的队列中,并在数据返回时...设置数据然后迭代函数队列(回调)并使用返回的数据调用它们。
如果您想获得技术,可以在通过队列时设置特定的QOS超时,在迭代开始时设置秒表,如果到达特定时间,则调用setTimeout返回队列继续迭代...我希望你得到:) - 它基本上节省了一定数量的setTimout调用只需要一个。
查看上面的Artem Bargers代码,您应该了解我的建议。