如何避免JavaScript / AngularJS中的HTTP请求竞争条件?

时间:2016-02-16 18:38:32

标签: javascript angularjs html5 rest http

我将JavaScript与AngularJS结合使用,最近遇到了HTTP请求竞争条件的一些问题。

出于演示目的,我会尝试简化问题: 假设您有多个范围。$ watch监听器启动并运行,其中一些可能会不时触发一些REST调用。

现在可能会有一些逻辑继续使这些侦听器互相触发,最终你最终会对具有不同参数的同一个url进行两次REST调用,而第一次调用的参数在此期间已经过时(所有这些都在几毫秒内发生)。两个回调基本上都是一样的,并且会覆盖一些变量"结果"在我的控制器或其他什么。

只要两个请求在服务器上占用相同的时间,它们将以相同的顺序返回,因此第二个调用的结果将覆盖第一个调用的一个,一切都很好。 但是,当然我们不能保证会发生这种情况,所以我们最终会遇到一个丑陋的竞争条件。

所以,现在我想知道是否有任何"最佳实践"或"设计模式"或其他"技巧"首先要避免这些问题。

我已经读过关于取消ajax请求并试用了这个解决方案 - 不幸的是,它在AngularJS中并不像在纯jQuery中那么容易,而且我的应用程序的结构并不是真的有利于这个一种解决方案。 然而,即使我使用ajax取消,我仍然会对相应的设计模式感兴趣,因为取消待处理的请求并不总是你想要在你的应用程序中做什么。

对于我的项目,一个工作的解决方案是记住每当我进行这样一个有问题的调用时最后的请求参数是什么,并且仅当最后使用的请求参数等于用于给定调用的请求参数时才解析结果,换句话说:

  • 使用param = 1调用f - >记得1
  • 使用param = 2调用f - >记住2,因此覆盖1
  • 第二次回电 - >检查是否使用了param(2)等于最后使用的param(2) - >解决
  • 第一次通话返回 - >检查是否使用了param(1)等于最后使用的param(1) - >不要解决

嗯,这在我的上下文中适用于我的程序,但当然它并不总是适用。有时您需要选择同时使用两个不同的参数进行两次相同类型的调用,而不会让您的代码拒绝它...

再说一次:你们首先知道这个问题有什么好的解决方案吗?拜托我......:D

1 个答案:

答案 0 :(得分:1)

我会使用承诺链接

  • 使用param = 1调用f - >记得1
  • 使用param = 2调用f - >来自1

然后在 1结算后,范围将仅由更新。

var httpPromise1 = $http(params1).then ( function onFulfilled(response) {
    $scope.data = response.data; //data set #1
});

//start second request
var startXHRpromise = $http(params2);

//chain fulFillment
var httpPromise2 = httpPromise1.then (function() {
    //chain with started XHR promise
    return startXHRpromise; 
}).then (function onFulfilled(response) {
    $scope.data = response.data; //data set #2
});

通过链接承诺,第二个数据集仅在 第一个数据集后放在范围内。

由于承诺可以通过另一个承诺(将进一步推迟其解决方案)来解决,因此可以在链中的任何点暂停/推迟承诺的解决。这使得实现强大的API成为可能。 1