2

I have a conceptual problem with NodeJS... I need to call a deferred function within a loop and use the response for the next iteration. How can I do that without blocking? Here is what I did but of course, response.rev doesn't get updated for the next iteration:

first.function().then(function(response) {
    for (var int = 0; int < $scope.files.length; int++) {
        call.function(response.rev).then(function (res) {
            response.rev = res.rev;
        }, function (reason) {
            console.log(reason);
        });
    }
});

Edit, my real code with Benjamin's help (still not working):

pouchWrapper.updateClient(clientManager.clientCleaner($scope.client)).then(function(response) {
    if ($scope.files != null) {
        var p = $q.when();
        for (var int = 0; int < $scope.files.length; int++) {
            var doc = $scope.files[int].slice(0, $scope.files[int].size);
            p = p.then(function(formerRes){
                return pouchWrapper.uploadFiletoDoc($scope.client._id, $scope.contract.policy_number + '&' + $scope.damage.number + '-' + $scope.files[int].name, res.rev, doc, $scope.files[int].type).then(function (res) {
                    return res;
                }, function (reason) {
                    console.log(reason);
                });
            });
        }
        return p;
    }
});
Charles
  • 50,943
  • 13
  • 104
  • 142
Nate
  • 7,606
  • 23
  • 72
  • 124

1 Answers1

4

You use .then for that. .then is the asynchronous version of the semicolon:

first.function().then(function(response) {
   var p = $q.when(); // start with an empty promise
   for (var int = 0; int < $scope.files.length; int++) {
      p = p.then(function(formerValue){
              return call.function(formerValue).then(function (res) {
                  // use res here as the _current_ value
                  return res; // return it, so that the next iteration can use it;
              });
      });
   }
   return p; // this resolves with the _last_ value
});
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • Yes, important technique. Recursive promise completions. – djechlin Jun 01 '14 at 22:08
  • I'm a bit lost here... the call.function is the function I would like to call with the _current_ value. – Nate Jun 01 '14 at 22:22
  • 1
    Yes, this basically "queues" the work up. Instead of looping over the function calls, we are queuing them, `then` means `"perform that action after this one, and give it as a parameter whatever this returns"` – Benjamin Gruenbaum Jun 01 '14 at 22:24
  • I tried what you wrote but I still get an error... TypeError: Cannot read property 'name' of undefined (see edit) – Nate Jun 01 '14 at 22:33
  • @ncohen now you just have an unrelated closure/loop problem, use a `.forEach` loop instead of a `for` loop and read http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – Benjamin Gruenbaum Jun 01 '14 at 22:35
  • Thanks but I'm still getting the same response.rev in my pouchWrapper.uploadFiletoDoc() function. I'm sorry if it's obvious but the concept of deferred functions is hard to catch for me. – Nate Jun 01 '14 at 22:54
  • Try reading http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call it may have some good pointers – Benjamin Gruenbaum Jun 01 '14 at 23:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/54937/discussion-between-ncohen-and-benjamin-gruenbaum). – Nate Jun 02 '14 at 15:29