2013-12-14 28 views
3

我有一個異步函數的這個問題。關鍵是「執行」不等待NotificationService.confirm回調的返回。AngularJS和一個服務內部的異步函數

我的意思是,它顯示了一個PhoneGap警報,但它並沒有等待評估哪個按鈕按下了用戶。所以,你可以在控制檯輸出undefined看到,而不是假/真/ 3的值

[編輯]

這是馬克西姆叫喊着提出的代碼,但它不工作尚未:

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

控制檯輸出

> Confirm: undefinedBEFORE用戶按壓按鈕)

> Callback function called!!!AFTER用戶按壓按鈕)

+0

示例闖入者:http://plnkr.co/edit/VfqJkJO2n7FFLWoTO2Bp – blacksoul

回答

0

問題是NotificationService.confirm("Do you want to confirm?", 'Yes!');返回承諾(A.E.異步)。

因此,它應該是這樣的:

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

演示Plunker

在你的情況下,由於navigator.notification.confirm使用回調,因此您可以嘗試返回從回調中解析

+0

即將完成,但尚未完成。我的意思是,如果我做一個console.log(結果)輸出是UNDEFINED還沒有被執行,直到用戶按下一個按鈕。我更新了請求代碼 – blacksoul

+0

,請簡要介紹一下倒票,謝謝 –

+0

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

2

問題是,在數據真正回來之前,您正在解決承諾。您需要讓onConfirm函數可以訪問NotificationService.confirm正在返回的承諾,並且只能在那裏調用resolve

+0

這樣做的竅門! :) 非常感謝! – blacksoul

1

$q通過讓方法引用一個可能還不存在的答案,讓它們註冊回調以在答案完成時運行來工作。這意味着如果您在與resolve()相同的代碼塊中調用defer(),則不會異步使用該承諾,因爲您在創建後立即解決該承諾。

您需要從confirm功能塊中取消deferred.resolve(data),並將其放入回調函數中。 resolve()總是進入某種回調函數,因爲回調函數是你如何等待異步事件。如果你能解決getter的承諾,那麼它並不是非同步的!

然後,改變你的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