2014-09-24 165 views
1

當承諾涉及到多個承諾時,我遇到了一些困難。這種混亂是有區別如何正確利用承諾 &他們與回調差異優勢。我注意到,無論承諾是否解決,有時會觸發回調,從而使得下面的實現不可靠。(除非我的語法&邏輯錯誤)
我閱讀了官方文檔並提出了這個問題,但我不確定它是否正確實現。

該註冊流程如下:
鏈接多個承諾(處理回調)

  • 用戶選擇一個別名 - >詳細別名+用戶ID(設備的通用唯一標識符)被髮送服務器側
  • 如果別名是可用的產生,ApiKey(令牌) ,用戶註冊,併發送回客戶端側(DB存儲)

Services.js

(function(angular) { 
    myApp.factory("deviceDB.Service", ['$resource', '$http', '$q', 
    function ($resource, $http , $q) { 

    return { 

//Second Promsie : After API token is generated server-side, store res in db 

     RegDevice: function (alias, apiKey, userID) { 
      var deferred = $q.defer(); 
      var configuration ; 
      var db = window.sqlitePlugin.openDatabase({name: "config.db"}); 
      setTimeout(function() { 

       db.transaction(function (tx) { 
        tx.executeSql('CREATE TABLE IF NOT EXISTS user_details (userID UNIQUE , alias TEXT, apiKey TEXT)'); 
        tx.executeSql("INSERT INTO user_details (userID, alias, apiKey) VALUES (?,?,?)", [userID, alias, apiKey], function (tx, res) { 

         deferred.resolve(configuration = true); 
        }, function (e) { 
         // console.log("ERROR: " + e.message); 
         deferred.reject(configuration = false); 
        }); 
       }); 

      }, 1000); 
      return deferred.promise; 
     }, 

//First Promsie: Register user server side & generate APi token 

     RegUser: function (alias, userID) { 

      var deferred = $q.defer(); 
      var pro; 
      pro = $resource('api/query/register', {'alias': alias, 'userID': userID}, 
       { query: { 
         isArray: false, 
         method: 'GET' } }); 

      setTimeout(function() { 
       pro.query(function (res) { 
        if (res.error) { 
         deferred.reject({ error : res.error, exists: res.exists, msg: res.message }); 
        } 
        else { 
         deferred.resolve({error : res.error , alias: res.alias , apiKey: res.apiKey, msg: res.message }); 
        } 
       }, function (e) { 
        deferred.reject({ errorStatus: e.status }); 

       }); 

      }, 1000); 
      return deferred.promise; 
     } 

    }; 

    }]); 

}(window.angular)); 


現在,在我的控制器中,我想鏈接上面的兩個承諾。我引用文檔中的以下內容:

then(successCallback, errorCallback, notifyCallback) - 無論何時該承諾已被解決或將被解決或被拒絕,只要結果可用,就會異步調用其中一個成功或錯誤回調。回調被調用一個參數:結果或拒絕原因。另外,在承諾被解決或被拒絕之前,通知回叫可以被稱爲零次或多次以提供進度指示。

  1. 什麼是具有回調,如果他們可以,如果承諾得到解決,無論火點?
  2. 在第一個Promise的成功回調中,我不應該呼叫例如Promise2嗎?如果無論Promise1正在解決如何解僱,那麼如何才能將Promise2鏈接起來才能在Promise1解決時觸發


我的嘗試:
Controller.js

myApp.controller('RegisterController', ['$scope', '$http', 'deviceDB.Service', 
    function ($scope , $http , deviceDB.Service) { 

    var Promise1 = deviceDB.RegUser($scope.alias, $scope.Device); 

// First promise - Validate with server 
    Promise1.then(function(data) 
        { 
         console.log(' Registration Server-Side successfully'); 
         $scope.apiKey = data.apiKey; 
         term.echo(data.apiKey); 

        }, function(e) 
        { 
         console.log('Registration Failed'); 
         term.echo(e.msg); 

        }) 

//Call Promise 2 & Store details Client-Side using .then() 

    .then(deviceDB.RegDevice($scope.alias, $scope.apiKey, $scope.Device), 
    function(d){ 
         console.log('Items Stored in DB successfully'); 
        }, function() 
        { 
         console.log('Items Stored in DB Failed'); 
        }); 
    }]); 

注:我知道這是一個不好的做法來存儲信息的客戶端,但是,我經過不同的概念(匿名消息),並沒有安全問題。

感謝您的時間

回答

1

你的第二個,然後調用似乎不正確,後

//Call Promise 2 & Store details Client-Side using .then() 

then佔用到3個參數then(successCallback, errorCallback, notifyCallback)你逝去的是:deviceDB.RegDevice($scope.alias, $scope.apiKey, $scope.Device)其立即評估,並承諾退還傳遞給函數then作爲成功函數,您的成功函數作爲errorCallback傳遞,您的失敗函數作爲notifyCallback傳遞。

我會嘗試以下

Promise1.then(function(data) 
{ 
    console.log(' Registration Server-Side successfully'); 
    $scope.apiKey = data.apiKey; 
    term.echo(data.apiKey); 

    return deviceDB.RegDevice($scope.alias, $scope.apiKey, $scope.Device) 

}, function(e) 
{ 
    console.log('Registration Failed'); 
    term.echo(e.msg); 

    return e; 

}).then(function(d) {/*all good*/}, function(e) {/* all bad */} 

通知調用RegDevice現在是一個功能塊內,並承諾從隨後封鎖您想從鏈返回。

+0

所以,如果我理解正確的,這裏Promise1接受3個參數,並返回承諾RegDevice是成功的回調(放置在第一arugment內) – Awena 2014-09-24 03:00:28

+0

它完美,事件被同步觸發,先Promise1然後是2.第二個then()[函數(d)成功/函數(e)錯誤promise2的回調?因此,如果我有3個承諾,我會在函數(d)返回中調用第三個...等等 – Awena 2014-09-24 03:11:37

+0

這是正確的。 – 2014-09-28 22:29:12

0

我覺得$q.serial是一個很好的鏈接承諾庫。這很容易使用,並處理很多事情,比如檢查鏈上的所有承諾是否真的有承諾。

這裏是一個小例子:

function do_all() {               
    var task_1 = function() {             
     return $http.get("some url")           
      .then(on_xhr_completed_fn, on_xhr_failed_fn);      
    }                   

    var task_2 = function(some_data) {           
     vm.bla = some_data;              
     return $http.get("other url")           
      .then(on_xhr_completed_fn, on_xhr_failed_fn);      
    }                   

    var task_3 = function(other_data) {           
     vm.bli = other_data;             
    }                  

    var tasks = [task_1, task_2, task_3];          

    return $q.serial(tasks)              
     .then(function() {              
      console.log("Finished tasks 1, 2 and 3!!!");      
     });                  
}