用于自解析对象的Javascript助手,用于Angulars $ resource等承诺

时间:2016-06-15 20:10:16

标签: javascript angularjs promise

Angulars $ resource具有很强的功能,可以返回注入其值并自动更新视图的对象。在$ resource服务中有一个Resource对象,它使用shallowClearAndCopy()将已解析的结果复制到自身。

我想链接从$ resource返回的promise,并获得类似于获取延迟结果的Resource对象。 (编辑代码示例以返回对象并需要参数。

var otherProperty = 'somethingChanging';
var lazyUser = $resource('/user/:userId').get({id:id});
var userDisplayNamePromise = lazyUser.$promise.then(transformResult);
function transformResult(user){
  return { displayName: user.firstname + ' ' + user.lastname,
           other: user[otherProperty]
         };
}

目前我必须做类似

的事情
userDisplayNamePromise.then(updateDisplayUser);
function updateDisplayUser(displayName){$scope.user = displayName;}

我希望做一些像

这样的事情
$scope.user = something(userDisplayNamePromise);

我找不到任何可以帮助我以这么简单的方式使用承诺的东西。有没有人提示?

我在github.com/burka/resolvling放了一个基本的工作示例。但我无法想象之前没有人这样做过吗?

2 个答案:

答案 0 :(得分:1)

有一些标准方法可以转换角度资源的响应。
这是一个fiddle
这是documentation

transformResponse - {function(data,headersGetter)| Array。} - 转换函数或此类函数的数组。 transform函数接受http响应主体和头部并返回其转换(通常是反序列化)版本。默认情况下,transformResponse将包含一个函数,该函数检查响应是否类似于JSON字符串,并使用angular.fromJson对其进行反序列化。要防止出现此行为,请将transformResponse设置为空数组:transformResponse:[]

这是示例代码

angular.module('services', ['ngResource']).
factory("someService", function ($resource) {
    return $resource(
        '/', {}, {
        get: {
            method: 'GET',
            transformResponse: function(data, headers){
                //MESS WITH THE DATA
                data = {};
                data.coolThing = 'BOOM-SHAKA-LAKA';
                return data;
            }
        }
    }

    );
});

答案 1 :(得分:1)

解包promises是异步应用程序的常规例程,应视为不可避免。

$resource中自填对象的概念对于异步工作流来说并不常见,取决于它的用法,它可能被视为反模式。

这是不可能的,因为displayName应该是一个标量值:

$scope.displayName = something(userDisplayNamePromise);

这是$q承诺无法在没有严重拼凑的情况下做出的事情(正如the repo所示):

$scope.displayObj = something(userDisplayNamePromise);

虽然这可能适用于像{{ displayObj.name }}这样的对象绑定:

$scope.displayObj = userDisplayNamePromise.$$state.value;

但它不应该在生产中使用 - 不仅因为不应该使用内部$$属性,还因为$$state.value可能包含拒绝承诺的值。

对于ES6环境或Babel-transiled ES5,co和生成器may be used to flatten promises

var wrap = (fn) => {
  return function(...args) {
    co(fn.bind(this, ...args));
  }
}

app.controller('AppController', ['$scope', '$q', wrap(function* ($scope, $q) {
  this.name = yield $q.resolve('World');
})]);

对于ngRoute和UI路由器,路由解析器可用于将已解析的值注入控制器并将值绑定到范围,这是摆脱解包代码的最常用方法。