Can you resolve an angularjs promise before you return it?

我试图编写一个返回承诺的函数。但有些时候,请求的信息可以立即获得。我想用一个承诺来包装它,这样消费者就不需要做决定了。

function getSomething(id) {
if (Cache[id]) {
var deferred = $q.defer();
deferred.resolve(Cache[id]); // <-- Can I do this?
return deferred.promise;
} else {
return $http.get('/someUrl', {id:id});
}
}

像这样使用它:

somethingService.getSomething(5).then(function(thing) {
alert(thing);
});

The problem is that the callback does not execute for the pre-resolved promise. Is this a legitimate thing to do? Is there a better way to handle this situation?

90355 次浏览

您忘了初始化 Cache 元素

function getSomething(id) {
if (Cache[id]) {
var deferred = $q.defer();
deferred.resolve(Cache[id]); // <-- Can I do this?
return deferred.promise;
} else {
Cache[id] = $http.get('/someUrl', {id:id});
return Cache[id];
}
}

如果我想在数组或对象中实际缓存数据,我通常是这样做的

app.factory('DataService', function($q, $http) {
var cache = {};
var service= {
getData: function(id, callback) {
var deffered = $q.defer();
if (cache[id]) {
deffered.resolve(cache[id])
} else {
$http.get('data.json').then(function(res) {
cache[id] = res.data;
deffered.resolve(cache[id])
})
}
return deffered.promise.then(callback)
}
}


return service


})

DEMO

简短的回答: 是的,您可以在返回 AngularJS 承诺之前解决它,它将按照您预期的方式运行。

JB Nizet's Plunkr,但重构工作在什么是最初的要求上下文(即一个函数调用服务)和实际在现场。

在军队里..。

function getSomething(id) {
// There will always be a promise so always declare it.
var deferred = $q.defer();
if (Cache[id]) {
// Resolve the deferred $q object before returning the promise
deferred.resolve(Cache[id]);
return deferred.promise;
}
// else- not in cache
$http.get('/someUrl', {id:id}).success(function(data){
// Store your data or what ever....
// Then resolve
deferred.resolve(data);
}).error(function(data, status, headers, config) {
deferred.reject("Error: request returned status " + status);
});
return deferred.promise;


}

在控制器里面。

somethingService.getSomething(5).then(
function(thing) {     // On success
alert(thing);
},
function(message) {   // On failure
alert(message);
}
);

我希望这对某人有帮助。我没有找到其他的答案非常清楚。

我喜欢使用工厂从我的资源中获取数据。

.factory("SweetFactory", [ "$http", "$q", "$resource", function( $http, $q, $resource ) {
return $resource("/sweet/app", {}, {
"put": {
method: "PUT",
isArray: false
},"get": {
method: "GET",
isArray: false
}
});
}]);

然后像这样在服务中展示我的模型

 .service("SweetService",  [ "$q", "$filter",  "$log", "SweetFactory",
function ($q, $filter, $log, SweetFactory) {


var service = this;


//Object that may be exposed by a controller if desired update using get and put methods provided
service.stuff={
//all kinds of stuff
};


service.listOfStuff = [
{value:"", text:"Please Select"},
{value:"stuff", text:"stuff"}];


service.getStuff = function () {


var deferred = $q.defer();


var promise = SweetFactory.get().$promise.then(
function (response) {
if (response.response.result.code !== "COOL_BABY") {
deferred.reject(response);
} else {
deferred.resolve(response);
console.log("stuff is got", service.alerts);
return deferred.promise;
}


}
).catch(
function (error) {
deferred.reject(error);
console.log("failed to get stuff");
}
);


promise.then(function(response){
//...do some stuff to sett your stuff maybe fancy it up
service.stuff.formattedStuff = $filter('stuffFormatter')(service.stuff);


});




return service.stuff;
};




service.putStuff = function () {
console.log("putting stuff eh", service.stuff);


//maybe do stuff to your stuff


AlertsFactory.put(service.stuff).$promise.then(function (response) {
console.log("yep yep", response.response.code);
service.getStuff();
}).catch(function (errorData) {
alert("Failed to update stuff" + errorData.response.code);
});


};


}]);

然后我的控制器可以包含它并公开它,或者仅仅通过引用注入的 Service.whatever 就可以在它的上下文中做它认为正确的事情

看起来工作正常。但是我对角度有点新鲜。 * 为了清晰起见,错误处理大多被忽略了

How to simply return a pre-resolved promise in Angular 1.x

坚定的承诺:

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

被拒绝的承诺:

return $q.reject( someValue );