0

I have a very large angularjs app, that sells stuff and has filters

It seems that we need to support people on flaky connection.

That means that if user selects 'used product' filter and then he unselects 'used product', there will be a 2 calls to the server via $http.

$http.get("reloadresults?used=true", function (response)  { $scope.items = response items; }); at 12:03:04 hours


$http.get("reloadresults?used=false", function (response)  { $scope.items = response items; }); at 12:03:05

Now, image there is a bottleneck or something and the first call with 'used=true' returns last, then there is a problem with the filters.

I know there is a $http interceptor in angularjs, based on promises, how would i fix this problem? So that requests are processed in the order they are sent, meaning 'used=true' and only then used=false.

Edit: cant block thread, cant refactor, just need for the promises to fullfil in the order they were first sent. I think ill post answer later.

Aflred
  • 4,435
  • 6
  • 30
  • 43

2 Answers2

0

I din't understand your question well but i think you are looking for

$q.all(valid_request)
Santosh Kumar
  • 205
  • 2
  • 6
  • I think there is something like a checkbox (any boolean trigger) that populates `$scope.items` upon `true` or `false` by calling different `$http.get` requests. With a delay there are no problems, but if you flick the checkbox very quickly, there will be a **race condition**, which OP want's to remove – Aleksey Solovey Apr 03 '18 at 12:48
0

You could indeed ensure that success handlers are called in the correct order by forming a queue (a promise chain) however it is simpler, and better in this case, to nullify the previous request each time a new request is made.

There's a number of ways in which this could be achieved. Here's one ...

function cancelPrevious(fn) {
    var reject_ = null;
    return function(x) {
        if(reject_) reject_(new Error('cancelled'));
        return Promise.race(fn(x), new Promise(function(_, reject) {
            reject_ = reject; // if reject_ is called before fn(x) settles, the returned promise will be rejected.
        }));
    };
}

which allows you to write ...

var get = cancelPrevious(function(str) {
    return $http.get(str);
});

... and to make requests from any number of event threads :

get('reloadresults?used=true').then(function(response) {
    // This function will be reached only if 
    // $http.get('reloadresults?used=true') fulfills 
    // before another get() call is made.
    $scope.items = response.items;
});

...

// This call causes the then callback above to be suppressed if not already called
get('reloadresults?used=false').then(function(response) {
    $scope.items = response.items;
});

Notes :

  • http requests are not canceled. Instead, the succuss path stemming from each request is made "cancelable" by racing against a rejectable promise.
  • side-effects included in the function passed to cancelPrevious() may be executed; in general, don't include such side effects.
Roamer-1888
  • 19,138
  • 5
  • 33
  • 44
  • this is not correct for IE, promise is not supported on IE11, please write your answer with the 'Q' promise library built into angularjs. – Aflred May 07 '18 at 10:19
  • Am miles from home right now. Back in a few days. Meanwhile see if you can fix it yourself. You will need to find a way to achieve `Promise.race()` - that's the only tricky bit. – Roamer-1888 May 07 '18 at 10:55