p4x
p4x

Reputation: 384

AngularJS .then is not a function()

Why I get this error when calling .then on a promise?

vm.submitPromise(...).then is not a function

A simplified version of my code is this:

    var submitPromise = function($q) {
      return function() {
        var deferred = $q.defer();
        //$scope.ngSubmitFunction();    

        // simulated async function
        $timeout(function() {
          deferred.resolve('data received!')
        }, 2000);
        return deferred.promise;
      }
    }

    function ngSubmit($form) {
      vm.submitDisabled = true;
      submitPromise().then(function() {
          vm.submitDisabled = false;
      });
    };

This is part from a directive managing forms. The purpose is for the Submit button to call a function that may have one or more async calls, and I need to wait for them to finish before enabling the submit button again.

Almost everywhere I read this happens when the function doesn't return a promise, but mine does (I believe). Doesn't it? what am I missing. I'm trying to debugg with a simulated async function $timeout and a .resolve in there (can be seen on the code) but I get the same error.

Upvotes: 0

Views: 280

Answers (4)

Dan
Dan

Reputation: 10538

submitPromise is returning a function, which in turn returns a promise, but you are not invoking the function. Given the signature of that method, you would need to use it like so:

function ngSubmit($form) {
  vm.submitDisabled = true
  submitPromise()().then(function () {
    vm.submitDsabled = false
  })
}

You probably wanted to do this instead:

var submitPromise = function($q) {
  var deferred = $q.defer();
  //$scope.ngSubmitFunction();    

  // simulated async function
  $timeout(function() {
    deferred.resolve('data received!')
  }, 2000);
  return deferred.promise;
}

Note the deferred pattern is deprecated and $q (along with the native Promise implementation in your browser) suggest a more constructor-based pattern instead:

function submitPromise($q) {
  return $q(function (resolve) {
    $timeout(function() {
      resolve()
    }, 2000)
  })
}

The reason for this is mainly because then your use of $q matches the ES6 spec, and also means you aren't imperatively managing the promise itself (which can lead to authoring mistakes).

Upvotes: 2

Valery Kozlov
Valery Kozlov

Reputation: 1577

not your question - your function just return function instead of promise but...

var submitPromise = function(){
    return $timeout(function(){
         return data;
    }, 2000);
};

this is the right way of writing your example

Upvotes: 0

Nikhil Aggarwal
Nikhil Aggarwal

Reputation: 28455

submitPromise returns a function. Hence, you need to execute it

Try following

 function ngSubmit($form) {
      vm.submitDisabled = true;
      submitPromise()().then(function() {
          vm.submitDisabled = false;
      });
    };

Upvotes: 0

Satpal
Satpal

Reputation: 133403

You are returning a function where as you need to return a promise.

var submitPromise = function($q) {
    var deferred = $q.defer();
    // simulated async function
    $timeout(function() {
      deferred.resolve('data received!')
    }, 2000);
    return deferred.promise;      
}

OR, You need to invoke the returned function like

function ngSubmit($form) {
    vm.submitDisabled = true
        submitPromise()().then(function () {
        vm.submitDsabled = false
    })
}

Upvotes: 0

Related Questions