简体   繁体   中英

How do I make a promise resolve as an object in the view?

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.

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)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM