• 关于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

  • 相关阅读:
    新概念英语(1-115)Knock! Knock!
    新概念英语(1-113)Small Change
    新概念英语(1-111)The most expensive model
    新概念英语(1-109)A Good Idea
    新概念英语(1-107)It's Too Small.
    新概念英语(1-105)Full Of Mistakes
    新概念英语(1-103)The French Test
    洛谷P4591 [TJOI2018]碱基序列(hash dp)
    洛谷P4492 [HAOI2018]苹果树(组合数)
    洛谷P4577 [FJOI2018]领导集团问题(dp 线段树合并)
  • 原文地址:https://www.cnblogs.com/liulangmao/p/4013465.html
Copyright © 2020-2023  润新知