简体   繁体   中英

AngularJS - “Chaining promises” with other functions in between

So I have this problem. I'm fairly new to angular and I've been told to modify a directive which manages forms to make the submit button disabled then enabled again when all the work is done.

Since the functions being called usually have async calls, simply adding code sequentially doesn't work.

var ngSubmit = function() {
  vm.disabled = true;
  $scope.ngSubmitFunction();
  vm.disabled = false;
}

Button is enabled before async calls under ngSubmitFunction() finish.

So I thought a promise would fix that and made something like:

var promise = function() {
  return $q(function (resolve) {$scope.ngSubmitFunction()});
}
var ngSubmit = function() {
  vm.disabled = true;
  promise().then(function() {
   vm.disabled = false;
  });
}

This doesn't output any error but never enables the button again (.then is never called).

Tried different kind of promises declaration, all with the same result, except for this one:

$scope.submitPromise = function() {
  return $q.when($scope.ngSubmitFunction());
}

This does call .then function, but again, doesn't wait for any child async function to finish. '.then' is called instantly, like the sequential version.

Have in mind that I don't know what's under ngSubmitFunction(). It is used by dozens developers and it may contain from 0 to multiple async calls. But typical scenario is something like:

ngSubmitFunction() calls func()

-- func() decides wether to call create() or update()

-- -- update() calls a elementFactory.update() which is an async call

-- -- -- elementFactory.update().then(function()) is called when finished.

-- -- -- -- At THIS point, I should enable the button again.

How can I achieve this? is there a way to chain promises with non-promises functions in between? or another way to make a code only execute when everything else is done? I thought about creating an event at DataFactory when an async call is over but if the update() function was calling to more than one async call this wouldn't work.

If you are using promises, your async functions should return promises, if they do it should work like this:

var ngSubmit = function() {
  vm.disabled = true;
  $scope.ngSubmitFunction().then(() => {
      vm.disabled = false;
  });
}

I don't know what's under ngSubmitFunction()

Then you're out of luck, promises won't help you here. Promises or $q.when cannot magically inspect the call and see what asynchronous things it started or even wait for them - ngSubmitFunction() needs to return a promise for its asynchronous results itself.

You need to make every function in your codebase which (possibly) does something asynchronous that needs to be awaitable return a promise. There's no way around this.

Well, in case someone wonders, we haven't found a solution to that (there probably isn't). So we will go with the adding returns to all the chain of functions to make sure the ngSubmitFunction recieves a promise and therefor can wait for it to finish before calling '.then'. Not only this makes it work for the cases where there's only one promise implied but it is also a good programming practice.

Cases with more than one promise are scarce so we will treat them individually on the controller itself.

Thank you all for your comments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM