关于angular的$resource中的isArray属性问题

在之前的文章中讲到了在使用$resource的时候,有一个isArray属性. 这个属性在两个地方有提到:

1. angular学习笔记(二十八)-$http(6)-使用ngResource模块构建RESTful架构

$resource的四个方法: query方法,get方法,save方法,remove方法,delete方法

这四个方法里,唯独query方法,它的isArray属性是true,所以,query接受到的数据是数组,而其余四个方法,接收到的数据必须不能是数组

2. angular学习笔记(二十八-附1)-$resource中的资源的方法

$resource的自定义方法: 比如该篇的栗子中使用的$charge方法,在定义自定义方法的时候,也要指定isArray属性.不指定的话默认是false.

如果我们不设置isArray为true,但是后台却给它返回一个数组资源,是会报错的.

那么,如果在使用get方法,save方法,remove方法,delete方法的时候,需要返回数组对象呢? 答案是不能的.因为$resource这个服务没有提供相应的配置方法.

那么,如果自定义一个方法,设置isArray为true,是不是就可以接受数组格式的返回值了呢? 答案是,要看情况!

比如下面这段代码:

var notePad = angular.module(‘notePad‘,[‘ngResource‘]);
notePad.factory(‘myNotes‘,[‘$resource‘,function($resource){
    return $resource(‘/notes/:id‘,{id:‘@id‘},{mysave:{method:‘POST‘,isArray:true}})
}]);
notePad.factory(‘loadNotes‘,[‘myNotes‘,‘$q‘,function(myNotes,$q){
    return function(){
        var defer = $q.defer();
        myNotes.query(function(notes){
            defer.resolve(notes);
        },function(err){
            defer.reject(err)
        });
        return defer.promise
    }
}]);
notePad.factory(‘loadNote‘,[‘myNotes‘,‘$q‘,function(myNotes,$q){
    return function(noteId){
        var defer = $q.defer();
        myNotes.get({id:noteId},function(note){
            defer.resolve(note);
        },function(err){
            defer.reject(err)
        });
        return defer.promise
    }
}]);
notePad.directive(‘notepad‘,[‘loadNotes‘,‘myNotes‘,function(loadNotes,myNotes){
    return {
        restrict:‘EA‘,
        templateUrl:‘template.html‘,
        scope:{},
        link:function(scope,iEle,iAttr){
            scope.editMode = false;
            scope.curText = ‘‘;
            scope.ifNew = true;
            loadNotes().then(function(data){scope.notes=data},function(data){});
            var editBox =  iEle.find(‘.edit‘);
            editBox.bind(‘keydown keyup‘,function(){
                scope.curText = $(this).html()
            });
            scope.editNote = function(id){
                scope.editMode = true;
                if(id != undefined){
                    scope.curText = scope.notes[id][‘content‘]
                }
                else {
                    scope.curText = ‘‘;
                }
            };
            scope.saveNote = function(){
                scope.editMode = false;
                if(scope.ifNew){
                    var newNote = new myNotes();
                    newNote.content = scope.curText;
                    newNote.title = scope.curText.length>5 ? scope.curText.substring(0,5)+‘...‘ : scope.curText;
                    newNote.id = scope.notes.length;
                    newNote.$mysave(function(data){console.log(data)})
                }
            }
        }
    }
}]);

内容比较多,只看关键部分代码:

1.myNotes服务通过$resource创建$resource()对象,然后给它添加自定义的mysave方法,设置isArray属性为false.

2.实例化一个newNote资源,然后调用自定义的$mysave方法

后台我们给它返回一个数组对象:

var notes = [{
    ‘title‘:‘吃饭‘,
    ‘content‘:‘吃饭啊‘,
    ‘id‘:0
},{
    ‘title‘:‘睡觉‘,
    ‘content‘:‘睡觉啊‘,
    ‘id‘:1
},{
    ‘title‘:‘喂兔子‘,
    ‘content‘:‘喂兔子啊‘,
    ‘id‘:2
}];
app.post(‘/notes/:id‘,function(req,res){
    var noteId = req.params.id;
    notes[noteId] = req.body;
    res.send(notes)
});

结果报错: 

这个很好理解,因为我们设置了isArray是false嘛.

然后我把isArray属性改为true:

结果还是报错:

百思不得其解后去看了angular-resource的源码,发现里面有这样一段:

var isInstanceCall = this instanceof Resource;
var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data));
if (action.isArray) {
                  value.length = 0;
                  forEach(data, function (item) {
                    if (typeof item === "object") {
                      value.push(new Resource(item));
                    } else {
                      // Valid JSON values may be string literals, and these should not be converted
                      // into objects. These items will not have access to the Resource prototype
                      // methods, but unfortunately there
                      value.push(item);
                    }
                  });
                }

注意这里的value对象,并非设置isArray为true时,它就是[],首先要求isInstanceCall是false,然后再判断isArray...

所以,这里的newNote是$resource()的实例,这样,isArray无论如何配置,它都不能接受数组格式的返回数据.并且必须配置为false.

所以这里应该这样做:


newNote.$mysave(function(data){console.log(data)})

//改为:
myNotes.mysave(newNote,function(data){console.log(data)});

不要使用资源实例的方法,而是直接使用$resource()的方法.这样就可以正确接收数组格式的返回值了.

angular这样设计,应该是符合RESTful架构风的(我猜的),因为提交一个资源,那么返回的也应该是一个资源,而不应该是整个数组,所以应该尽量避免这种做法.这里只是我自己做练习的时候遇到这样的情况.

完整代码参考: angular指令实战-notepad

时间: 2024-10-04 06:13:11

关于angular的$resource中的isArray属性问题的相关文章

angular学习笔记(二十八-附2)-$resource中的promise对象

下面这种promise的用法,我从第一篇$http笔记到$resource笔记中,一直都有用到: HttpREST.factory('cardResource',function($resource){ return $resource('/card/user/:userID/:id',{userID:123,id:'@id'},{charge:{method:'POST',params:{charge:true},isArray:false}}) }); HttpREST.factory('h

angular学习笔记(二十八-附1)-$resource中的资源的方法

通过$resource获取到的资源,或者是通过$resource实例化的资源,资源本身就拥有了一些方法,比如$save,可以直接调用来保存该资源: 比如有一个$resource创建的服务: var service = angular.module('myRecipe.service',['ngResource']); service.factory('Recipe',['$resource',function($resource){ return $resource('/recipe/:id',

angular在模板中使用属性引发Cannot read property 'xxx' of undefined

在使用ng2的过程中,发现模板中如下方式 <li *ngFor="let item of model"> {{item.name}} </li> 不会又任何问题. 如果是一下未使用结构指令方式,直接使用组件的属性 <li > {{model.name}}</li> 就会报错null错误,一开始百思不得其解,后来搞明白,model是异步请求获取的数据,在定义的时候let mode:any 时是属于unde值,而这时组件模板已经开始渲染了,也

http请求头中的Content-Type属性在angular 和 node中的用法

post请求的请求体有以下两种格式: 1. 字符串: 'name=code_bunny&age=12' 这种格式的请求体,需要配置请求头 'Content-Type':'application/x-www-form-urlencoded' 2. json: {name:'code_bunny',age:12} 这种格式的请求体,需要配置请求头 'Content-Type':'application/json;charset=UTF-8' 注意: 请求体格式和请求头的Content-Type类型必

java spring中对properties属性文件加密及其解密

原创整理不易,转载请注明出处:java spring中对properties属性文件加密及其解密 代码下载地址:http://www.zuidaima.com/share/1781588957400064.htm 加密类: package com.zuidaima.commons.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import

深入理解jQuery、Angular、node中的Promise

最初遇到Promise是在jQuery中,在jQuery1.5版本中引入了Deferred Object,这个异步队列模块用于实现异步任务和回调函数的解耦.为ajax模块.队列模块.ready事件提供基础功能.在用jQuery操作DOM的时候对Promise的使用欲不够强烈,最近学习node和Angular,需要用js写业务逻辑和数据操作代码的时候这种场景需求就出来了.一般来说事件适合在交互场景中运用,因为用户的行为本来就是分散的,而promise这样的流程控制适合在后台逻辑中处理业务. //j

Android自己定义控件而且使其能够在xml中自己定义属性

为什么要自己定义View android开发中自己定义View的优点是显而易见的.比方说以下的这个顶部导航,它被设计出如今应用的每一个界面,但每次的内容却不尽同样.我们不能在每一个layout资源中都配置一组同样的View吧?假设使用<include layou="@layout/xxx"/>标签,尽管攻克了布局文件的重用性,可是相关View的初始化设置还是没可以重用(集中),须要每次都採用view.findViewById(id)来初始化他们. 有了对"可重用性

@Resource注解省略name属性后的行为

@Resource有一个name属性,该属性值为所要注入的Bean实例的id,类似于<property.../>元素的ref属性,不过在spring中允许省略name属性值,省略后在以下情况中代表不同的行为 注解标注set方法时省略name属性,如setXXX(),则name值默认为xXX,去掉“set”,首字母小写. 注解直接标注变量时省略name属性,则那么name值默认与所标注变量名相同. 值得注意的是:如@Resource省略name属性后,按其默认规则没有找到所需要注入的Bean时,

【转载】在Angular 2/Typescript中声明全局变量的最佳方式是什么?

问题详细描述 我想在Typescript语言中的Angular 2中声明一些全局可见的变量.最佳的实践方法是? 推荐的实现方法 这是最简单的解决方案,无需使用Service或Observer: 将全局变量放在文件中然后导出它们. // // ===== File globals.ts // 'use strict'; export const sep='/'; export const version: string="22.2.2"; 要在另一个文件中使用这些全局变量,请使用impo