2014-05-09 22 views
32

Il mio servizio è:

myApp.service('userService', [ 
    '$http', '$q', '$rootScope', '$location', function($http, $q, $rootScope, $location) { 
    var deferred; 
    deferred = $q.defer(); 
    this.initialized = deferred.promise; 
    this.user = { 
     access: false 
    }; 
    this.isAuthenticated = function() { 
     this.user = { 
     first_name: 'First', 
     last_name: 'Last', 
     email: '[email protected]', 
     access: 'institution' 
     }; 
     return deferred.resolve(); 
    }; 
    } 
]); 

Chiamo questo nel mio file config via:

myApp.run([ 
    '$rootScope', 'userService', function($rootScope, userService) { 
    return userService.isAuthenticated().then(function(response) { 
     if (response.data.user) { 
     return $rootScope.$broadcast('login', response.data); 
     } else { 
     return userService.logout(); 
     } 
    }); 
    } 
]); 

Tuttavia, si lamenta che then non è una funzione. Non sto restituendo la promessa risolta?

risposta

17

Dal vostro metodo di servizio:

function serviceMethod() { 
    return $timeout(function() { 
     return { 
      property: 'value' 
     }; 
    }, 1000); 
} 

E nel controller:

serviceName 
    .serviceMethod() 
    .then(function(data){ 
     //handle the success condition here 
     var x = data.property 
    }); 
+0

@BenjaminGruenbaum Sì, hai ragione, non sapevo che '$ timeout' restituisce effettivamente una promessa, serviceMethod può essere abbreviato in: return $ timeout (function() {return {property: 'value'};}, 1000); – Brocco

+7

Questo potrebbe funzionare, ma non è certamente un approccio consigliato per restituire le promesse –

+0

@BenjaminGruenbaum che ho fatto, ora restituendo la promessa che genera $ timeout. – Brocco

31

Restituire la promessa, restituire deferred.promise.
È l'API di promessa che ha il metodo "then".

https://docs.angularjs.org/api/ng/service/$q

Calling determinazione non restituisce una promessa segnala solo la promessa che la promessa si risolve in modo che possa eseguire il 'poi' logica.

modello di base come segue, sciacquare e ripetere
http://plnkr.co/edit/fJmmEP5xOrEMfLvLWy1h?p=preview

<!DOCTYPE html> 
<html> 

<head> 
    <script data-require="[email protected]*" data-semver="1.3.0-beta.5" 
     src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script> 
    <link rel="stylesheet" href="style.css" /> 
    <script src="script.js"></script> 
</head> 

<body> 

<div ng-controller="test"> 
    <button ng-click="test()">test</button> 
</div> 
<script> 
    var app = angular.module("app",[]); 

    app.controller("test",function($scope,$q){ 

    $scope.$test = function(){ 
     var deferred = $q.defer(); 
     deferred.resolve("Hi"); 
     return deferred.promise; 
    }; 

    $scope.test=function(){ 
     $scope.$test() 
     .then(function(data){ 
     console.log(data); 
     }); 
    }  
    }); 

    angular.bootstrap(document,["app"]); 

</script> 

+0

Come sarà la promessa avere risolto allora? Il '.then' non verrà mai attivato – Shamoon

+2

per risolvere il deferred prima di restituire deferred.promise. – mccainz

+0

@Shamoon deferred.resolve(); è risolto nel momento in cui lo chiami perché non c'è un valore dato in. Suggerirei invece di scrivere deferred.resolve ("Ciao"); scrivi solo deferred.resolve(); per ottenere una promessa vuota risolta. Ma potresti anche usare $ q.when(); per ottenere una promessa vuota valida e risolvibile ;-). – Sebastian

0

Prova questo:

myApp.service('userService', [ 
    '$http', '$q', '$rootScope', '$location', function($http, $q, $rootScope, $location) { 
     var deferred= $q.defer(); 
     this.user = { 
     access: false 
     }; 
     try 
     { 
     this.isAuthenticated = function() { 
     this.user = { 
      first_name: 'First', 
      last_name: 'Last', 
      email: '[email protected]', 
      access: 'institution' 
     }; 
     deferred.resolve(); 
     }; 
    } 
    catch 
    { 
     deferred.reject(); 
    } 

    return deferred.promise; 
    ]); 
+0

Qualcuno potrebbe dirmi perché questo è contrassegnato per downvote? – premsh

2

Ecco il codice corretto per il vostro servizio:

myApp.service('userService', [ 
    '$http', '$q', '$rootScope', '$location', function($http, $q, $rootScope, $location) { 

    var user = { 
     access: false 
    }; 

    var me = this; 

    this.initialized = false; 
    this.isAuthenticated = function() { 

     var deferred = $q.defer(); 
     user = { 
     first_name: 'First', 
     last_name: 'Last', 
     email: '[email protected]', 
     access: 'institution' 
     }; 
     deferred.resolve(user); 
     me.initialized = true; 

     return deferred.promise; 
    }; 
    } 
]); 

Poi regolatore dovrebbe allineare di conseguenza:

myApp.run([ 
    '$rootScope', 'userService', function($rootScope, userService) { 
    return userService.isAuthenticated().then(function(user) { 
     if (user) { 
     // You have access to the object you passed in the service, not to the response. 
     // You should either put response.data on the user or use a different property. 
     return $rootScope.$broadcast('login', user.email); 
     } else { 
     return userService.logout(); 
     } 
    }); 
    } 
]); 

Pochi punti da notare sul servizio :

  • Esporre in un servizio solo ciò che deve essere esposto. L'utente deve essere tenuto internamente ed essere accessibile solo dai getter.

  • Nelle funzioni, utilizzare "me", che è il servizio per evitare casi limite di questo con javascript.

  • Ho intuito cosa intendeva fare inizializzare, sentitevi liberi di correggermi se ho indovinato.

1

Per più breve JavaScript-Code utilizzare questo:

myApp.service('userService', [ 
    '$q', function($q) { 
    this.initialized = $q.when(); 
    this.user = { 
     access: false 
    }; 
    this.isAuthenticated = function() { 
     this.user = { 
     first_name: 'First', 
     last_name: 'Last', 
     email: '[email protected]', 
     access: 'institution' 
     }; 
     return this.initialized; 
    }; 
    } 
]); 

Voi sapete che si perde il legame con userService.user sovrascrivendo con un nuovo oggetto invece di impostare solo le proprietà degli oggetti?

Ecco cosa intendo come esempio del mio plnkr.Codice co esempio (esempio di funzionamento: http://plnkr.co/edit/zXVcmRKT1TmiBCDL4GsC?p=preview):

angular.module('myApp', []).service('userService', [ 
    '$http', '$q', '$rootScope', '$location', function ($http, $q, $rootScope, $location) { 
    this.initialized = $q.when(null); 
    this.user = { 
     access: false 
    }; 
    this.isAuthenticated = function() { 
     this.user.first_name = 'First'; 
     this.user.last_name = 'Last'; 
     this.user.email = '[email protected]'; 
     this.user.access = 'institution'; 
     return this.initialized; 
    }; 
}]); 

angular.module('myApp').controller('myCtrl', ['$scope', 'userService', function ($scope, userService) { 
    $scope.user = userService.user; 
    $scope.callUserService = function() { 
     userService.isAuthenticated().then(function() { 
      $scope.thencalled = true; 
     }); 
    }; 
}]); 
1

Per tornare una promessa risolto, è possibile utilizzare:

return $q.defer().resolve(); 

Se è necessario risolvere qualcosa o restituire i dati:

return $q.defer().resolve(function(){ 

    var data; 
    return data; 

}); 
+0

Ho [pubblicato] (http://stackoverflow.com/a/30779102/901944) una versione ancora più breve. –

82

Come restituire semplicemente una promessa pre-risolta in Angular

Risolto promessa:

return $q.when(someValue); // angular 1.2+ 
return $q.resolve(someValue); // angular 1.4+, alias to `when` to match ES6 

promessa Rifiutato:

return $q.reject(someValue); 
+1

Questo è esattamente quello che stavo cercando. Un bel modo breve per restituire un valore statico quando si sopprimono chiamate di servizio http. – Richard

Problemi correlati