首页 > 解决方案 > 我得到 TypeError: Converting circular structure to JSON error in twilio join to channel

问题描述

阅读此文档https://www.twilio.com/blog/implementing-programmable-chat-php-laravel-vue-js 我尝试在登录时添加我的 Laravel 8 / jQuery 3.5.1 / vue 2.6 / Bootstrap 4.5 聊天用户选择另一个用户我运行 axios 请求以检查是否先前创建了频道(或创建新频道)。在客户端部分

connectClientWithUsername(){
    this.tc.username = this.loggedUser.name

    let vm = this;
    axios.post('/admin/team-chat/check_channel', {
        sender_id : vm.loggedUser.id,
        receiver_id : vm.selectedTeamUser.id
    })
        .then(({data}) => {
            console.log('check_channel data::')
            console.log(data)
            
            vm.newChartCreated= data.newChartCreated // Flag if new chat was created
            vm.currentChatChannelName= data.currentChatChannelName // Name of requested channel
            vm.fetchAccessToken(vm.tc.username, vm.connectMessagingClient);

        })
        .catch(error => {
            console.error(error)
            popupAlert('Team Chat', error.response.data.message, 'warn')
            vm.is_page_loaded = true
        })
},

fetchAccessToken(username, handler) {
    let vm = this;
    axios.post('/token', {
        identity: this.tc.username,
        device: 'browser'
    })
        .then(function (response) {
            handler(response.data);
        })
        .catch(function (error) {
            console.log(error);
        });
},

在 app/Http/Controllers/Admin/TeamChatController.php 中的服务器部分:

public function check_channel(Request $request)
{
    $requestData = $request->all();
    $chatName= "public_oo_team_chat_" . $requestData['sender_id'] . '_' . $requestData['receiver_id'];
    $newChartCreated = false;
    $chatChannel = null;
    try {
        $channel = $this->twilio->chat->v2->services(config('app.TWILIO_SERVICE_SID'))
                                          ->channels($chatName)
                                          ->fetch();

    } catch(RestException $e) {
        $channel = $this->twilio->chat->v2->services(config('app.TWILIO_SERVICE_SID'))
            ->channels->create([
                'uniqueName'    => $chatName,
                'friendlyName'  => $chatName,
                'type'          => 'public'  // New channel was created
            ]);
        if($channel->sid) {
            $chatChannel= new ChatChannel(); // Ref to newly created channel was saved in db
            $chatChannel->sender_id= $requestData['sender_id'];
            $chatChannel->receiver_id= $requestData['receiver_id'];
            $chatChannel->channel_name= $chatName;
            $chatChannel->last_chat_at= Carbon::now(config('app.timezone'));
            $chatChannel->save();
        }
        $newChartCreated= true;

    }
    return response()->json([
        'message' => '',
        'chatChannel' => $chatChannel,
        'newChartCreated' => $newChartCreated, // return name of current Channel
        'currentChatChannelName' => $chatName], HTTP_RESPONSE_OK);
} // check_channel


public function getToken(Request $request)
{
    $this->identity = $request->identity;
    $token = new AccessToken(
        $this->twilio_account_sid,
        $this->twilio_api_key,
        $this->twilio_api_secret,
        3600,
        $this->identity
    );
    // Create Chat grant
    $chat_grant = new ChatGrant();
    $chat_grant->setServiceSid($this->service_sid);

    // Add grant to token
    $token->addGrant($chat_grant);
    // render token to string
    echo $token->toJWT();
}

当我从服务器获取令牌时,我创建客户端并尝试连接到通道

    connectMessagingClient(token) {  // connects the user to the Twilio Chat client.
        // Initialize the Chat messaging client
        let vm = this;

        this.tc.accessManager = new Twilio.AccessManager(token);

        new Twilio.Chat.Client.create(token).then(function(client) {
            vm.tc.messagingClient = client;
            vm.updateConnectedUI();
            vm.connectToActiveChannel(client) // I try to connect to channel I need

            // vm.tc.messagingClient.on('channelAdded', _.throttle(vm.loadChannelList));
            // vm.tc.messagingClient.on('channelRemoved', _.throttle(vm.loadChannelList));
            // vm.tc.messagingClient.on('tokenExpired', vm.refreshToken);
        });
    },

    connectToActiveChannel(messagingClient) {
        let vm = this

        // Get all public channels
        messagingClient.getPublicChannelDescriptors().then(function(channels) {
            for (let i = 0; i < channels.items.length; i++) {
                const channel = channels.items[i];
            }
            vm.tc.channelArray = channels.items;

            vm.tc.channelArray.forEach(vm.addChannel); // Check for selected channel
        });

    },

    addChannel(channel){
        console.log('addChannel channel::')
        console.log(typeof channel)
        if (channel.uniqueName === this.currentChatChannelName) {
            this.tc.generalChannel = channel;
            console.log('FOUND  this.tc.generalChannel!!!')
            console.log( this.tc.generalChannel )
            return this.joinChannel(channel);
        }
    },

    joinChannel(_channel) { // the member joins the channel (general or a personally created channel)
        console.log(" joinChannel   _channel");
        console.log(_channel);
        let vm = this;
        return _channel.join()
            .then(function(joinedChannel) {
                console.log('Joined channel ' + joinedChannel.friendlyName);
                vm.updateChannelUI(_channel);
                vm.tc.currentChannel = _channel;
                vm.loadMessages();
                return joinedChannel;
            })
            .catch(function(err) {
                alert("Couldn't join channel " + _channel.friendlyName + ' because ' + err);
            });
    },

在 joinChannel 我得到了错误:

vue.common.dev.js?4650:630 [Vue warn]: Error in render: "TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'l'
    |     property '_fsm' -> object with constructor 'o'
    --- property 'context' closes the circle"

在线的:

return _channel.join()

我在浏览器的控制台中看到:

https://prnt.sc/wekctphttps://prnt.sc/wekspu

看起来我的流程中有一个错误,但在我看来,我将有效对象传递给 line :

_channel.join

为什么会出现错误以及如何修复?

谢谢!

标签: javascriptlaravelvue.jstwilio

解决方案


Twilio 开发人员布道者在这里。

在这段代码中:

    connectToActiveChannel(messagingClient) {
        let vm = this

        // Get all public channels
        messagingClient.getPublicChannelDescriptors().then(function(channels) {
            for (let i = 0; i < channels.items.length; i++) {
                const channel = channels.items[i];
            }
            vm.tc.channelArray = channels.items;

            vm.tc.channelArray.forEach(vm.addChannel); // Check for selected channel
        });

    }

这一行似乎没有做任何事情(它遍历通道描述符列表,channel为每个描述符创建一个新的 const,然后立即丢弃它。

然后,将 设置vm.tc.channelArray为通道描述符列表并调用vm.addChannel每个描述符。

注意这里getPublicChannelDescriptors()返回一个ChannelDescriptor对象列表。ChannelDescriptors 不能被加入并包含在请求通道时有关通道的数据快照。

要加入频道,您需要先调用getChannel()频道描述符,然后执行其余代码。

让我知道这是否有帮助。


推荐阅读