PubNub ChatEngine 在使用 Angular 重新加入 1-1 聊天后"Converting circular structure to JSON"错误



我第一次尝试使用Angular来了解这个PubNub ChatEngine示例 https://github.com/pubnub/chat-engine-examples/tree/master/angular/simple

在演示中,当您从列表中单击用户时,将生成具有随机名称的新频道并邀请用户加入。因此,如果您离开聊天,请再次单击用户,您将连接到新频道。

我正在尝试做 1-1 聊天室,您可以离开而不是重新加入,因此更改了频道名称以单击用户 uuid。现在,如果我离开频道,请重新加入它并尝试发送消息,它没有显示在列表中,尽管它正在发送并且您正在聊天的用户收到它。

在控制台中,我在开始键入(如正在运行聊天引擎键入指示器)和提交后收到"未捕获(承诺)类型错误:将循环结构转换为 JSON"。

我想这与使用 splice() 方法从全局范围内删除聊天并在重新加入后添加新聊天有关。它在演示中有效,因为每次都会获得新频道并将其删除,但如果现在使用相同的频道,则不会。 我尝试使用 splice() 来代替看看会发生什么。如果我关闭聊天并重新加入它,它会保留在 DOM 中,并且新的聊天会添加到范围内,因此在 DOM 中有两个相同的聊天元素。如果我在第二个上键入并发送消息,它不会显示在它上面,而是显示在第一个试图关闭的消息上。 我怎样才能让它正常工作,splice() 是否可以在我的情况下使用,并且我错过了导致错误的其他内容?

$scope.leave = (index) => {
$scope.chat.leave();
$scope.chats.splice(index, 1);
//$scope.chats.slice(index, 1);
//$scope.chats.splice( $scope.chats.indexOf($scope.chat), 1 );
}

angular.module('chatApp', ['open-chat-framework'])
.run(['$rootScope', 'ngChatEngine', function($rootScope, ngChatEngine) {
$rootScope.ChatEngine = ChatEngineCore.create({
publishKey: 'pub-c-d8599c43-cecf-42ba-a72f-aa3b24653c2b',
subscribeKey: 'sub-c-6c6c021c-c4e2-11e7-9628-f616d8b03518'
}, {
debug: true,
globalChannel: 'chat-engine-angular-simple'
});
// bind open chat framework angular plugin
ngChatEngine.bind($rootScope.ChatEngine);
// set a global array of chatrooms
$rootScope.chats = [];
}])
.controller('Chat', function($scope) {
$scope.chat.plugin(ChatEngineCore.plugin['chat-engine-typing-indicator']({
timeout: 5000
}));
// every chat has a list of messages
$scope.messages = [];
// we store the id of the lastSender
$scope.lastSender = null;
// leave a chatroom and remove from global chat list
$scope.leave = (index) => {
$scope.chat.leave();
$scope.chats.splice(index, 1);
}
// send a message using the messageDraft input
$scope.sendMessage = () => {
$scope.chat.emit('message', {
text: $scope.messageDraft
});
$scope.messageDraft = '';
}
// when we get notified of a user typing
$scope.chat.on('$typingIndicator.startTyping', (event) => {
event.sender.isTyping = true;
});
// when we get notified a user stops typing
$scope.chat.on('$typingIndicator.stopTyping', (event) => {
event.sender.isTyping = false;
});
// function to add a message to messages array
let addMessage = (payload, isHistory) => {
// if this message was from a history call
payload.isHistory = isHistory;
// if the last message was sent from the same user
payload.sameUser = $scope.messages.length > 0 && payload.sender.uuid == $scope.messages[$scope.messages.length - 1].sender.uuid;
// if this message was sent by this client
payload.isSelf = payload.sender.uuid == $scope.me.uuid;
// add the message to the array
$scope.messages.push(payload);
}
// if this chat receives a message that's not from this sessions
$scope.chat.search({
event: 'message'
}).on('message', function(payload) {
// render it in the DOM with a special class
addMessage(payload, true);
})
// when this chat gets a message
$scope.chat.on('message', function(payload) {
// render it in the DOM
addMessage(payload, false);
});
})
.controller('OnlineUser', function($scope) {
// create a new chat
$scope.newChat = function(user) {
// define a channel
let chan = user.uuid;
// create a new chat with that channel
let newChat = new $scope.ChatEngine.Chat(chan);
// we need to auth ourselves before we can invite others
newChat.on('$.connected', () => {
// this fires a private invite to the user
newChat.invite(user);
// add the chat to the list
$scope.chats.push(newChat);
});
};
})
.controller('ChatAppController', function($scope) {
// create a user for myself and store as ```me```
$scope.ChatEngine.connect(new Date().getTime(), {}, 'auth-key');
$scope.ChatEngine.on('$.ready', (data) => {
$scope.me = data.me;
$scope.me.plugin(ChatEngineCore.plugin['chat-engine-random-username']($scope.ChatEngine.global));
$scope.ChatEngine.global.plugin(ChatEngineCore.plugin['chat-engine-online-user-search']());
// when I get a private invit
$scope.me.direct.on('$.invite', (payload) => {
let chat = new $scope.ChatEngine.Chat(payload.data.channel);
chat.onAny((a,b) => {
console.log(a)
});
// create a new chat and render it in DOM
$scope.chats.push(chat);
});
// bind chat to updates
$scope.chat = $scope.ChatEngine.global;
// hide / show usernames based on input
$scope.userSearch = {
input: '',
fire: () => {
// get a list of our matching users
let found = $scope.ChatEngine.global.onlineUserSearch.search($scope.userSearch.input);
// hide every user
for(let uuid in $scope.chat.users) {
$scope.chat.users[uuid].hideWhileSearch = true;
}
// show all found users
for(let i in found) {
$scope.chat.users[found[i].uuid].hideWhileSearch = false;
}
}
};
$scope.userAdd = {
input: '',
users: $scope.userAdd,
fire: () => {
if($scope.userAdd.input.length) {
$scope.userAdd.users = $scope.ChatEngine.global.onlineUserSearch.search($scope.userAdd.input);
} else {
$scope.userAdd.users = [];
}
}
};
});
});
<div class="container-fluid" ng-controller="ChatAppController">
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-block">
<h4 class="card-title">ChatEngine</h4>
<p class="card-text">Your are {{me.state.username}} with uuid {{me.uuid}}</p>
</div>
<ul id="online-list" class="list-group list-group-flush">
<li class="list-group-item" ng-repeat="(uuid, user) in chat.users" ng-hide="user.hideWhileSearch" ng-controller="OnlineUser">
<a href="#" ng-click="newChat(user)"> {{user.state.username}}</a>
<span class="show-typing" ng-show="user.isTyping">is typing...</span>
</li>
</ul>
<div class="card-block">
<form class="send-message" ng-submit="userSearch.fire()">
<div class="input-group">
<input id="usernameSearch" type="text" class="form-control message" placeholder="Search for Username" ng-change="userSearch.fire()" ng-model="userSearch.input">
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">Search</button>
</span>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-6">
<div id="chats" class="row" ng-repeat="chat in chats" ng-controller="Chat">
<div class="chat col-xs-12">
<div class="card">
<div class="card-header">
<div class="col-sm-6">
{{chat.channel}}
</div>
<div class="col-sm-6 text-right">
<a href="#" ng-click="leave($index)" class="close">x</a>
</div>
</div>
<ul class="list-group list-group-flush online-list-sub">
<li class="list-group-item" ng-repeat="(uuid, user) in chat.users" ng-hide="user.hideWhileSearch" ng-controller="OnlineUser">
{{user.state.username}}
<span class="show-typing" ng-show="user.isTyping">is typing...</span>
</li>
</ul>
<div class="card-block">
<div class="log">
<div ng-repeat="message in messages" ng-class="{'hide-username': message.sameUser, 'text-muted': message.isHistory, 'text-xs-right': !message.isSelf}">
<p class="text-muted username">{{message.sender.state.username}}</p>
<p>{{message.data.text}}</p>
</div>
</div>
<p class="typing text-muted"></p>
<form class="send-message" ng-submit="sendMessage(chat)">
<div class="input-group">
<input ng-model="messageDraft" ng-change="chat.typingIndicator.startTyping()" type="text" class="form-control message" placeholder="Your Message...">
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">Send</button>
</span>
</div>
</form>
</div>
<hr />
<div class="card-block">
<h6>Add a user to this chat</h6>
<fom ng-submit="userAdd.fire()">
<div class="input-group">
<input id="usernameSearch" type="text" class="form-control message" placeholder="Add User" ng-change="userAdd.fire()" ng-model="userAdd.input">
</div>
</form>
<ul class="list-group list-group-flush online-list-sub">
<li class="list-group-item" ng-repeat="(uuid, user) in userAdd.users" ng-controller="OnlineUser">
<a href="#" ng-click="invite(user, chat.channel)"> {{user.state.username}}</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

通过升级到最新的 ChatEngine 版本可以解决问题。根据ChatEngine github存储库问题:

它在聊天engine@0.9.5中正常工作,我使用的是聊天-engine@0.8.4

最新更新