2013-12-14 3 views
3

У меня возникла проблема с функцией async. Дело в том, что «исполнение» не ждет возврата обратного вызова NotificationService.confirm.AngularJS и функция async внутри службы

Я имею в виду, что показывает предупреждение PhoneGap, но он не ждет, чтобы оценить, какая кнопка нажала на пользователя. Таким образом, вы можете увидеть в консоли вывода undefined вместо ложных/Истинные/3 значения

[EDIT]

Это код, предложенный Максим Shoutin, но пока не работает:

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 (ПЕРЕД пользователь нажал кнопку)

> Callback function called!!! (ПОСЛЕ пользователь нажал кнопку)

+0

Пример plunker: http://plnkr.co/edit/VfqJkJO2n7FFLWoTO2Bp – blacksoul

ответ

0

Проблема заключается NotificationService.confirm("Do you want to confirm?", 'Yes!'); возвращается обещание (к.э. асинхронный).

Так оно и должно быть что-то вроде:

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"); 
        })  

Только для демонстрации мы можем использовать $timeout для имитации асинхронной вызов:

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

В вашем случае, поскольку navigator.notification.confirm использует обратный вызов, поэтому вы можете попробовать вернуться разрешить из callback.

+0

Это почти сделано, но оно еще не закончено. Я имею в виду, если я делаю console.log (результат), выход НЕ УКАЗАН, но пока выполнение не приостанавливается, пока пользователь не нажмет кнопку. Я обновил (-а) запрос с кодом – blacksoul

+0

, пожалуйста, дайте краткое описание при голосовании, спасибо –

+0

Plunker: http://plnkr.co/edit/VfqJkJO2n7FFLWoTO2Bp – blacksoul

2

Проблема заключается в том, что вы решаете обещание, прежде чем данные действительно вернутся. Вы должны дать своему onConfirm функции доступа к обещанию, что NotificationService.confirm отдает назад, и только звоните resolve внутри.

+0

Это сделало трюк !!! :) Большое спасибо! – blacksoul

1

$q методы, позволяющие методам иметь ссылку на ответ, который еще не существует, и позволяя им регистрировать обратные вызовы, которые будут выполняться, когда ответ будет выполнен. Это означает, что если вы вызываете defer() в том же кодовом блоке, что и resolve(), вы не используете это обещание асинхронно, так как вы разрешаете его сразу же после его создания.

Вам необходимо переписать deferred.resolve(data) из функционального блока confirm и поместить его в свою функцию обратного вызова. resolve() должен всегда выполняет функцию обратного вызова, так как функции обратного вызова - это то, как вы ожидаете асинхронного события. Если вы можете решить обещание в геттере, то это не очень асинхронно!

Затем измените метод onConfirm выглядеть следующим образом:

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); 
}; 

Теперь мы не решим обещание, пока мы не в notificaiton обратного вызова, что означает, что пользователь сделал свой выбор, и мы разрешаем его с помощью решения пользователя.

И, наконец, вы заметите, что если onConfirm находится вне вашей службы, у него не будет доступа к объекту deferred, который необходимо решить. Переместите onConfirm в свою функцию confirm, чтобы он имел доступ к закрытию этой переменной.

+0

Это сделало трюк !!! :) Большое спасибо! – blacksoul

Смежные вопросы