问题
Basically what I want to do, is to assign some model value from function call that resolves promise. Like so
value = someFun()
This is a service from which I call this function
app.factory('SomeService', function($q) {
return {
someFun: function() {
var d = $q.defer();
try {
d.resolve("hi");
} catch (e) {
d.reject(e);
}
return d.promise.then(function(text){
return text;
});
}
};
});
Here is the HTML code
<div ng-init="value = 'yes'">
<pre>{{value |json}}</pre>
</div>
<button type="button" ng-click="value = someFun()">click me</button>
And this is in the controller
$scope.someFun = SomeService.someFun;
Here is plnkr
http://plnkr.co/edit/qO5ofBXZDsi3cS3bBnT8
Right now it returns an empty object. What is wrong?
EDIT: As already answered below, yes this is one way, but let's say I want to call SomeService.someFun in ngRepeat?
EDIT2: HERE IS THE ANSWER -> Angular UI Bootstrap modal inside ngRepeat
回答1:
Generally if you want to use something that is updated asynchronously to appear in a view without having to write controller code as well (which is the case in your question, as you wanted to call the function inside ng-view), then you need to return a blank placeholder object, and either merge the result of the promise into it, or update a property of that object which you can reference in the view.
Your question is too abstract to know the exact way to approach this to make sense for your application, but here is the general (and abstracted) idea plunker here:
.factory('promiseService', function($q){
return {
someDeferredThing: function(){
var placeholder = {};
var d = $q.defer();
d.promise.then(function(text){
placeholder.text = text;
});
d.resolve("hi");
return placeholder;
}
}
)
The service returns an object which is updated by the promise, and not a promise itself. If you return a promise then you have to deal with .then()
etc. to get the value.
.controller('appCtrl', function($scope, promiseService){
$scope.deferredResult = promiseService.someDeferredThing();
});
This is how you assign the value to the scope.
$scope.deferredResult.text
will be undefined until the promise resolves, then it will become defined and resolve to "text"
. As such, your view should handle the undefined state for a short duration - usually it's very simple to do that with ng-show
.
回答2:
Controller.js:
$scope.someFun = function () {
return someservice.someFun().then(function (data) {
$scope.value = data;
});
}
someservice.js:
function someFun() {
var d = $q.defer();
try {
d.resolve("hi");
} catch (e) {
d.reject(e);
}
return d.promise;
}
html:
<div ng-init="value = 'yes'">
<pre>{{value |json}}</pre>
</div>
<button type="button" ng-click="someFun()">click me</button>
回答3:
promise.then()
returns a promise as stated in the AngularJS Documentation. If you want to get the value, you should do it like this:
SomeService.someFun.then(function(text) {
$scope.someFun = text;
});
Update:
Create a $scope
function that will assign value to the value
variable instead.
CONTROLLER
$scope.setValue = function() {
SomeService.someFun.then(function(text) {
$scope.value = text;
});
};
HTML
<div ng-init="value = 'yes'">
<pre>{{value |json}}</pre>
</div>
<button type="button" ng-click="setValue()">click me</button>
回答4:
To expand upon Ed Hinchliffe's answer, if you're wanting to return an actual object, which will in turn be populated once a promise is resolved, you can do something like this. (Similar to his answer, but using $http as an example async operation) Then instead of copying the result into a hard coded property of the returned reference to placeholder
, it copies all properties from the object received from $http into the existing reference to placeholder
which has already been returned. This is of course, assuming you are wanting to return an object. I'm assuming this is similar to how $resource works internally when returning objects.
function getObjectToBeFilledByPromise() {
var placeholder = {}; // Create a reference to return
var deferred = $q.defer(); // This will handle your promise
deferred.promise.then(function(data) { // Once our promise is resolved, populate object
// Add all properties of data into the existing placeholder reference which was already returned
for(var attr in data) {
placeholder[attr] = data[attr];
}
});
// Some Asynchronous Operation...
$http({
method: 'GET',
url: yourUrl
})
.success(function(data) {
deferred.resolve(data); // Resolve promise, which will be handled above
})
// Return reference as it exists now.
// It will be populated once the promise is resolved
return placeholder;
}
来源:https://stackoverflow.com/questions/25261872/angularjs-promise-returning-empty-object