gpt4 book ai didi

javascript - 如何将两个 $firebaseArray 合并为一个?

转载 作者:行者123 更新时间:2023-11-28 06:33:30 24 4
gpt4 key购买 nike

目前,我正在使用 AngularFire 学习 Firebase,但我遇到了一个问题。

我想从 Firebase 查询两个列表,一个是每个经过身份验证的用户都可以获取的公共(public)消息列表(在数据库中称为 messages),另一个是只有创建者才能获取的消息列表(私有(private))消息users_private/{uid}/messages)。对私有(private)消息的限制是通过 Firebase 规则完成的。

使用 $firebaseArray() 获取两个数组是可行的,但如何将它们组合起来,以便可以在一个 ng-repeat 中使用它们?问题是与 Firebase 的同步必须有效($add$remove 方法),但事实并非如此。如果我发现类似 array.concat(userArray) 的同步。坏了。

我可能可以执行两次 ng-repeat 并复制我的 HTML 标记,但我希望将其放在一个地方以保持干燥。对于两个列表,以后的过滤也会很困难,例如按日期过滤。私有(private)消息和公共(public)消息的模型方案是相同的。这些对象仅在可见性属性 privatepublic 上有所不同。

Users 集合仅存储用户名,并且对任何经过身份验证的用户在浏览器控制台中可见。这是必需的,这样我就可以获取用户名及其 uid。因此,这些数据不是私有(private)的,这就是为什么我添加了 users_private 以及其他限制。

为什么是两个数组?

我想让私有(private)数据仅对创建者可见。现在,它是一个聊天应用程序,但以后您可以将其视为公共(public)帖子和只有作者才能看到的私有(private)帖子。

首先,我尝试使用 messages 集合中的属性 visibility 来实现此目的,但后来我注意到您无法使用 firebase 限制对其的访问规则。 See rules are not filters

数据结构如下所示(messages、users、users_private 是顶级文档): data structure

如果您有其他想法如何创建私有(private)和公共(public)消息,欢迎提出任何想法。但我认为我走在正确的道路上。

我的代码基于angularFire seed project .

我也想列出私有(private)消息的 View 如下所示: chat view

这是我的 Controller ,我想在其中组合数组(代码的一些详细信息:users 是 ng-route 的解析值,用户也可以通过 $ 获取rootScope.user 和当前登录的用户以及 userSvc 在这里用于从用户的 uid 中获取用户的名称)以及 `ng 的标记片段-重复´:

(function(angular) {
"use strict";

var app = angular.module('myApp.chat', [
'ngRoute', 'firebase.utils', 'firebase', 'angularSpinner'
]);

app.controller('ChatCtrl', ['$scope',
'messageList', 'privateMessageList', 'user', 'userSvc', '$q',
function($scope, messageList, privateMessageList, user, userSvc, $q) {
$scope.messages = [];
$scope.user = user;

$scope.getDisplayName = userSvc.getDisplayName;

// messageList security set with firebase rules
messageList.$loaded().then(function() {
if (user) {
$scope.messages = messageList; //comibinedlist;
privateMessageList.$loaded().then(function(list) {
$scope.showSpinner = false;
$scope.privateMessages = privateMessageList;
//$scope.displayMessages = [messageList,
// privateMessageList];
//updateDisplayMessages(messageList, privateMessages);
console.log('messageList', messageList, 'private list', privateMessageList, list);
});
}
});

$scope.addMessage = function(newMessage) {
var dataList; // storage users/messages for private or /messages
if (newMessage) {
if (newMessage.visibility === 'private') {
dataList = $scope.privateMessages;
console.log('added', dataList);
//angular.extend($scope.messages, $scope.privateMessages);
} else {
dataList = $scope.messages; //$scope.messages.$add(newMessage);
}

// add a timestamp
angular.extend(newMessage, {
timestamp: Firebase.ServerValue.TIMESTAMP
});

dataList.$add(newMessage);
}
};

$scope.removeMessage = function(msg) {
var dataList;
if (msg.visibility === 'private') {
dataList = $scope.privateMessages;
} else {
dataList = $scope.messages;
}
$scope.displayMessages.$remove(msg).then(function(ref) {
console.log('removed', msg, ref.key() === msg.$id, ref.key(), msg.$id); // true
});
// $scope.messages.$remove(msg).then(function(ref) {
// console.log('removed', msg, ref.key() === msg.$id, ref.key(), msg.$id); // true
// });
};
}
]);

app.factory('privateMessageList', [
'fbutil', '$firebaseArray', '$rootScope',
function(fbutil, $firebaseArray, $rootScope) {
var ref = fbutil.ref('users_private', $rootScope.user.uid, 'messages')
.limitToLast(10);
console.log('privMsg user', $rootScope.user.uid);
return $firebaseArray(ref);
}
]);

app.factory('messageList', ['fbutil', '$firebaseArray',
function(fbutil, $firebaseArray) {
var ref = fbutil.ref('messages').limitToLast(10);
return $firebaseArray(ref);
}
]);

app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.whenAuthenticated('/chat', {
templateUrl: 'chat/chat.html',
controller: 'ChatCtrl',
//authRequired: true,
// resolve: {
// // forces the page to wait for this promise to resolve before controller is loaded
// // the controller can then inject `user` as a dependency. This could also be done
// // in the controller, but this makes things cleaner (controller doesn't need to worry
// // about auth status or timing of accessing data or displaying elements)
// user: ['userSvc', function(userSvc) {
// return userSvc.getUser();
// }]
// }
});
}
]);

})(angular);
<div class="list-group" id="messages" ng-show="messages.length">
<div class="list-group-item" ng-repeat="message in messages | reverse">
<strong>{{getDisplayName(message.uid) || 'anonymous'}}: </strong>{{message.text}}
<button href="#" class="btn btn-default btn-xs" ng-click="removeMessage(message)" ng-if="user.uid === message.uid"><i class="fa fa-remove"></i>
</button>
<span class="badge">{{message.visibility}}</span>
</div>
</div>

以下是我当前的 Firebase 规则(尚未检查 user_private 的规则):

{
"rules": {
// todo: add other user lists and only keep the username in users/ --> anyone with auth can get that list
// add users_profile (email etc.), users_roles
// user roles stored separately so we can keep it secure and only accessible (read & write) with uid
"users": {
".read": "auth !== null",
"$user_id": {
//".read": "auth !== null", // && ( auth.uid === $user_id )",
".write": "auth !== null && ( auth.uid === $user_id )"
}
},
"users_private": {
"$user_id": {
".read": "auth !== null", //&& ( auth.uid === $user_id )",
".write": "auth !== null && ( auth.uid === $user_id )"
}
},
"messages": {
".read": "auth != null", //"(data.child('visibility').val() === 'public')",
"$message": {
//".read": true,
/*".read": "(data.child('visibility').val() === 'public') ||
//( auth.uid == data.child('uid').val() ) ||
( root.child('users').child(auth.uid).child('admin').val() === true )", // the world can view public and author can view their message or admins (just for debugging)*/
".write": "(data.child('uid').val() == auth.uid ) || ( auth.uid == newData.child('uid').val() ) ||
(root.child('users').child(auth.uid).child('admin').val() === true)" // only owner or admin can write, user = 10, moderator = 20, admin = 999
}
/*"$uid": {
".write": "auth.uid == $uid" // only owner can write/edit to it if not new
}*/
}
}
}

最佳答案

首先,我对 Angular/AngularFire 不太了解,但我认为你的问题实际上非常简单并且与框架无关:Firebase 强制你将帖子存储在两个单独的集合中,所以现在你必须合并这两个集合获取它们后。

请注意,users_private/{uid}/messages 不是一个数组,而实际上是一个映射/对象。这可能解释了为什么 Array.concat 不能完成这项工作。如果 messages 也是类似 map /对象,您可以使用诸如

之类的算法

How can I merge properties of two JavaScript objects dynamically?

合并它。另一种可能性是将数据转换为不可变映射:

https://facebook.github.io/immutable-js/

除了不变性(这很好)之外,你还可以使用 immutable-js 获得更好的 API;例如,支持 OOTB 合并 map 。

关于javascript - 如何将两个 $firebaseArray 合并为一个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34491935/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com