0

I am using angular1 and I have 4 functions that need to execute synchronously. Assume those functions are : f1 , f2, f3 , f4 and need to run in that order. f1, f2, f3, f4 are functions that are used independently in other cases. I have only one usecase where I need to execute them sequentially. I know I have to use promise and I tried as :

self.selectionPromise = function(){
            var deferred = $q.defer();

            console.log("Inside promise");
            self.f1();

            return deferred.promise;
        };

And then use it as:

self.updateSelectedFile = function () {
            self.selectionPromise()
                .then(self.f2() )
                .then(self.f3() )
                .then(self.f4() )
        }

Does not seem to resolve my issue. I am seeing error: **TypeError: Cannot read property 'then' of undefined and additionally, the functions are not in order **

May I get help on how to use expect to synchronise these 4 functions?

Here is the hint on the code structure:

Function F1:

self.setRecordCount = function () 
{
    var deferred = $q.defer();
    if (!self.selectedFile) 
    {
        self.recordCount = 0;
        return;
    }


    self.fileInfo = {fileLocation: self.folderPath + self.selectedFile};

    FileService.getRecordCount(self.fileInfo)
        .then(
            function (count) 
            {
                //do something
            },
            function (errResponse) 
            {
                self.recordCountError = "Error while getting record count for file: " + self.folderPath + self.selectedFile;
            }
        )
        .then(function finishUp(response) 
        {
            console.log("returning from recordCount");
        })
    ;

    deferred.resolve("RecordCount");
    deferred.promise;
}

function F2:

self.detectDelimiter = function () {
    var deferred = $q.defer();
    if (!self.selectedFile) {
        return;
    }

    self.fileInfo = {fileLocation: self.folderPath + self.selectedFile};
    FileService.detectFileDelimiter(self.fileInfo)
        .then(
            function ( fileDelimiter ) {

                //do something

            },
            function( errResponse ) {
                self.displayError = "Error attempting to detect file delimiter";
            }
        )
        .then(function finishUp(response){
            console.log("returning from detectDelimeter");
        })
    ;

    deferred.resolve("Detect Delimeter");
    deferred.promise;
}

Now I am trying to synchronise these 2 functions F1 and F2 and make third function call:

self.updateSelectedFile = function () 
{
    self.setRecordCount()
        .then(function(){
            console.log("promise done : setRecordCount")
            self.detectDelimiter()
                .then(function(){
                    console.log("promise done : detectDelimiter")
                    self.generateFilePreviewInfo();
                })
        })
}
VictorGram
  • 2,521
  • 7
  • 48
  • 82
  • This question seems to duplicate of https://stackoverflow.com/questions/20100245/how-can-i-execute-array-of-promises-in-sequential-order – Alejandro Sep 24 '18 at 05:55
  • If f1() is doing asynchronous work, and you want to wait for this asynchronous work to be finished before calling f2, then f1 itself must return a promise. Post the code of f1. – JB Nizet Sep 24 '18 at 06:22
  • each of f1 to f4 itself has asynchronous http calls. and f4 is dependent on f3. f3 is dependent on f2 and so on. – VictorGram Sep 24 '18 at 14:42
  • Then they should all return promises that are resolved when the asynchronous work is done. Again, if you want help, port their code. – JB Nizet Sep 24 '18 at 17:10
  • @JBNizet : I have added code snippets – VictorGram Sep 24 '18 at 19:25
  • Remove `()` in all three cases. (snippet 2) – Kevin B Sep 24 '18 at 19:29

1 Answers1

2

You have to chain the promise on each functions callback. If you have any asynchronous code inside any function , make sure that resolve is calling after the successful callback of inner async code

class HomeCtrl {
  constructor($scope, $q) {
    'ngInject';

    this.name = "AngularJS";
    execute();
    function execute() {
      selectionPromise().then(function (data) {
        f1().then(function (data) {
          f2().then(function (data) {
            f3().then(function (data) { });
          });
        });
      });
    }

    function selectionPromise() {
      var deferred = $q.defer();
      console.log("Inside promise");
      deferred.resolve("someData")
      return deferred.promise;
    };
    function f1() {
      var deferred = $q.defer();
      console.log("Executed 1 ")
      deferred.resolve("Some Data from F1")
      return deferred.promise;
    }
    function f2() {
      var deferred = $q.defer();

      console.log("Executed 2 ")
      deferred.resolve("Some Data from F2")
      return deferred.promise;
    }
    function f3() {
      var deferred = $q.defer();
      console.log("Executed 3 ")
      deferred.resolve("Some Data from F3")
      return deferred.promise;
    }
  }

}

export default HomeCtrl;

Sample Demo created in StackBlitz

Jameel Moideen
  • 7,542
  • 12
  • 51
  • 79
  • This is a great example that gives a clear idea how it should be implemented. And I tried your code and that works. However my code is still in disorder. I guess because of the reason that they are making http calls inside. Like ' FileService.detectFileDelimiter' is making a http call. Similarly 'FileService.getRecordCount' is making http call. Any idea? Thanks for your help anyway – VictorGram Sep 24 '18 at 20:50
  • @Patty from your code I can understand that you are calling .resolve in the last line instead you should call after the successful callback of getRecordCount() method. In my stackblitz I have added function 4 to understand the same – Jameel Moideen Sep 24 '18 at 20:53
  • Thx much. That was it – VictorGram Sep 24 '18 at 22:12