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

标签 javascript angular chat pubnub

我正试图围绕这个第一次使用 Angular 的 PubNub ChatEngine 示例进行思考 https://github.com/pubnub/chat-engine-examples/tree/master/angular/simple

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

我正在尝试做 1-1 聊天室,你可以离开而不是加入,所以将 channel 名称更改为单击用户 uuid。现在,如果我离开 channel ,重新加入并尝试发送消息,它不会显示在列表中,尽管它正在发送并且与您聊天的用户会收到它。

在控制台中,我在开始输入时(聊天引擎输入指示器正在运行)和提交后收到“未捕获( promise )TypeError:将循环结构转换为 JSON”。

我想这与使用 splice() 方法从全局范围中删除聊天以及加入新聊天后添加有关。它在演示中有效,因为每次都会获取新 channel 并将其删除,但如果现在使用相同的 channel 则不会。 我尝试改用 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 repo issue :

it's working correctly with chat-engine@0.9.5, I was using chat-engine@0.8.4

关于javascript - 使用 Angular 加入 1-1 聊天后 PubNub ChatEngine "Converting circular structure to JSON"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49098089/

相关文章:

javascript - 是否可以使用纯 HTML、CSS、JS 发送通知?

firebase - 使用 firestore 计算群聊中看不见的消息

ios - 如何将 PFQueryViewController 用作 UITableViewController 的 subview ?

javascript - FlatList 将单个项目转换为数组

javascript - 按字符串数组过滤javascript对象数组

angular - 在 canActivate 中获取父路由参数

jquery - Angular cli theme.js 中的奇怪错误 :236 Uncaught TypeError: $.holdReady 不是函数

javascript - Angular 中的 session 超时警告弹出窗口

javascript - react : Suggestion is not showing in the drop-down

javascript - jquery-bootgrid 如何将两个数据值合并到同一列中