3

I am having this issue with an async function. The point is that the "execution" is not waiting for the return of NotificationService.confirm callback.

I mean, that shows a PhoneGap alert, but it's not waiting for evaluate which button pressed the user. So, you can see in the console output undefined instead of false/true/3 values

[EDIT]

This is the code proposed by Maxim Shoutin, but it isn't working yet:

NotificationController.js

angular.module('app').controller("NotificationController", function($rootScope) {

    $rootScope.cancel_button = function() {
      var confirm = NotificationService.confirm("Do you want to confirm?", 'Yes!');

      confirm.then(function(result) {
        console.log('Confirm: ' + result);
        if(confirm)   $location.path('/menu');
      }, function(result) {
        console.log('No data returned');
      })
    }

   /* Additional controller code... */
}

NotificationService.js

angular.module('app').factory("NotificationService", function() {

  // Callback function
  var onConfirm = function(button) {
    console.log('Callback function called!!!');
    if(button == 1)       return false;
    else if(button == 2)  return true;
    else if(button == 3)  return 3;
    else                  return false; // dismissed without press button
  };

 return {
     confirm : function(alert_msg, title, buttonsArray) {

        var deferred = $q.defer();

        if(buttonsArray == null) {
             buttonsArray = ['Cancel', 'OK'];
        }

         var data = navigator.notification.confirm(
                        alert_msg,      // message
                        onConfirm,      // callback
                        title,          // title
                        buttonsArray    // buttonsArray
                    );

         deferred.resolve(data);
         return deferred.promise;
      }
  }
}

CONSOLE OUTPUT

> Confirm: undefined (BEFORE user pressed the button)

> Callback function called!!! (AFTER user pressed the button)

1

3 Answers 3

2

The problem is you're resolving the promise before the data has actually come back. You need to give your onConfirm function access to the promise that NotificationService.confirm is handing back, and only call resolve inside there.

Sign up to request clarification or add additional context in comments.

Comments

1

$q works by letting methods have a reference to an answer that may not exist yet, and letting them register callbacks to be run when the answer is done. That means that if you call defer() in the same code block as resolve(), you're not really using the promise asynchronously, since you resolve it immediately after it was made.

You need to remnove deferred.resolve(data) from your confirm function block, and put it in your callback function instead. resolve() should always go in a callback function of some sort, because callback functions are how you wait for an asynchronous event. If you can resolve a promise in the getter, then it's not really asynchronous!

Then, change your onConfirm method to look like this:

var onConfirm = function(button) {
  console.log('Callback function called!!!');
  var result= false;

  // if(button == 1)    default case

  if(button == 2)  { result = true; }
  else if(button == 3)  { result = 3; }

  // else               default case

 deferred.resolve(result);
};

Now, we don't resolve the promise until we're in the notificaiton callback, which means the user has made their selection, and we resolve it with the user's decision.

Finally, you'll notice that if onConfirm is outside of your service, it won't have access to the deferred object it needs to resolve. Move onConfirm into your confirm function so it will have closure access to that variable.

Comments

0

The problem is NotificationService.confirm("Do you want to confirm?", 'Yes!'); returns promise (a.e. async).

So it should be something like:

var confirm = NotificationService.confirm("Do you want to confirm?", 'Yes!');

// now confirm is a promise
confirm.then(function (result) {
            console.log('Confirm: ' + confirm);

            if(confirm)   $location.path('/round/actual');                                    
                    }, function (result) {
                        alert("Error: No data returned");
                    })    

Only for demo we can use $timeout to simulate async call:

app.factory('NotificationService', function($q,$timeout) {

  // Callback function
  var onConfirm = function(button) {

    var state;

    console.log('Callback function called!!!');
    if(button == 1)       state = 'working!';
    else                  state = false; // dismissed without press button

    return state;
  };


  var factory =  {
     confirm : function(alert_msg, title, buttonsArray) {

       var deferred = $q.defer();

      $timeout(function () {
         var state =  onConfirm(1); // simulate call callback after 3 sec
         deferred.resolve(state);
       }, 3000);

       return deferred.promise;
      }
  }
  return factory;
});

Demo Plunker

In your case, since navigator.notification.confirm uses callback so you can try to return resolve from callback.

4 Comments

It's almost done, but it's unfinished yet. I mean, if I do a console.log(result) the output is UNDEFINED yet because the execution is not being "paused" until user press a button. I updated the ask with the code
Hmm, in Plunker, the data is single method but it should be some value like array or model that you get by async way
I can't add the navigator.notification because it's from Cordova.js and it does not work here. Cause of that I let that function. You can modify with anything simple to test. Thanks you for your time!
see my edit i posted, i saw in docs of phonegap that navigator.notification uses callback only

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.