由于多个AJAX请求而导致竞争条件

时间:2009-08-14 07:53:12

标签: javascript ajax xmlhttprequest race-condition

我的问题如下。我写了一个类AJAXEngine,它在构造函数中创建一个新的XMLHttpRequest对象。该类包含一个名为responseAnalyser的方法,该方法在XMLHttpRequest对象的“onreadystatechange”发生更改时被调用。 所以现在我创建了让我们说4个AJAXEngine =>的实例4个XMLHttpRequest对象。

现在我有另一个类DataRequester,它有一个数组属性dataReq,它包含AJAXEngine的实例。整个程序中只有一个DataReqeuster实例! DataRequester有一个名为callWhenFinished的函数。函数调用该函数 AJAXEngine的responseAnalyser并递减DataRequester实例的变量。

但是,我认为会出现竞争条件。我怎么能用JavaScript来预防它们?

function AJAXEngine
{
 this.httpReqObj = //create new XMLHttpRequest Object
 this.obj;
 this.func;
}
AJAXEngine.prototype.responseAnalyser = function()
{
 if(this.httpReqObj.readState == 4)
 {
  this.func.call(this.obj);
 }
}
AJAXEngine.prototype.fireReq = function(o, f)
{
 this.obj = o;
 this.func = f;
 // fire ajax req
}

function DataRequester()
{
 this.dataReq = new Array();
 this.test = 4;

 for(var i = 0; i < 4; i ++)
 {
  this.dataReq[i] = new AJAXEngine();
 }
}
DataRequester.prototype.callWhenFinished = function()
{
 this.test --;
}

5 个答案:

答案 0 :(得分:1)

不确定这是否有帮助,但看起来您正在尝试创建托管连接池。几年前我做了一个在这里仍然可以正常工作:

DP_RequestPool Library

池确保请求按照您提供的顺序进行(当然,它们可以根据性能以任何顺序返回)使用您定义的同时请求(受系统限制)。您可以为不同目的实例化多个池。

如果没有别的,这可能会给你一些想法。

答案 1 :(得分:0)

首先:大多数面向AJAX的浏览器支持约定“只有2个同时发送到同一域的请求”。因此,如果你开始4,那么其中2个将被起床。

您的DataReqeuster / singleton /可以包含变量'test'数组,因此不是跨多个实例共享单个变量,而是创建多个数据实例。因此,要计算结果,您需要对'test'数组求和。

答案 2 :(得分:0)

你需要实现一个临时互斥(想法是一个启发式检查bool并将其设置为true如果它是假的那么做身体,否则睡觉(settimeout?) - 这显然是一个非常糟糕的启发式没有人会实施,因为它不是线程安全的,但这是你如何处理竞争条件的一般概念)。

我相信至少有一个在网络上创建互斥体的例子,但我没有详细查看它 - 它有一些批评者,但我不知道在javascript中实现'线程安全'的另一种方法。我从来没有需要实现js的'线程安全',但是我开始研究是否必须在javascript中处理竞争条件。

答案 3 :(得分:0)

你不能仅仅因为没有内置的睡眠功能就可以在javascript中使用互斥锁。

请参阅:Is there an equivalent Javascript or Jquery sleep function?

此外,无法确保互斥锁中的布尔标志不会与另一个线程同时被访问,布尔值本身则需要互斥锁...依此类推等等。你需要像java中的Synchronized关键字这样的东西在javascript中可用,而这根本不存在。我遇到过我担心线程安全问题的情况,但如果发生错误但尚未发生错误,那么无论如何使用替代计划的代码。

所以我的建议是,如果你得到一个错误,可能不是因为竞争条件。

答案 4 :(得分:0)

你如何看待以下文章?我刚在谷歌找到它

http://www.developer.com/lang/jscript/article.php/3592016