Reputation: 330
I'm trying to wrap a third party library to return an object that resolves into an object that can be displayed in the view, similar to how $resource() works. I'm aware that I can manually do .then() on the promise and then set the value, but I wanted the result to seamlessly return similar to how I can do:
this.Value = $resource("/someresource").get();
How would I change the below SomeThirdPartyFunction() to return an object that resolves in the view.
Here's an example of what I'm trying to do:
angular.module('testApp', []).controller('TestController', function ($timeout, $q) {
var TestController = this;
var SomeThirdPartyFunction = function () {
var Deferred = $q.defer();
var Promise = Deferred.promise;
$timeout(function () {
Deferred.resolve("abcd");
}, 3000);
return Promise;
};
TestController.Value = SomeThirdPartyFunction();
/* I don't want to do this:
SomeThirdPartyFunction().then(function(Value) {
TestController.Value = Value;
});*/
});
And here's a plunker: https://plnkr.co/edit/HypQMkaqXmFZkvYZXFXf?p=preview
Every example I've seen using promises just wraps $http calls, but I haven't seen any examples of calling third party libraries that return promises that resolve into objects.
Upvotes: 1
Views: 745
Reputation: 48968
Under-the-hood, $resource uses angular.copy:
function myResourceGet(params) {
var emptyObj = {};
emptyObj.$resolved = false;
emptyObj.$promise = $http.get(url, {params:params})
.then(function(response) {
angular.copy(response.data, emptyObj);
}).finally(function() {
emptyObj.$resolved = true;
});
return emptyObj;
}
From the Docs:
angular.copy Overview
Creates a deep copy of
source
, which should be an object or an array.
- If a destination is provided, all of its elements (for arrays) or properties (for objects) are deleted and then all elements/properties from the source are copied to it.
The $resource service only works when the data is an object or an array. It does not work with primitives such as a string or number.
Upvotes: 1
Reputation: 3968
From the AngularJS document:
It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data.
So instead of return a promise, you can do something like this:
var SomeThirdPartyFunction = function() {
var getAComplextObject = function() {
return {
number: 42,
method: function() {
return this.number + 1;
}
};
};
var returnValue = {};
$timeout(function() {
console.log("Resolved!");
Object.assign(returnValue, getAComplextObject());
}, 1000);
return returnValue;
};
You can wrap it in a promise and make the promise part of the return value, doing that you can make it thenable (aka a Promise)
Upvotes: 1