猫鼬findOneAndUpdate()阻止socket.io请求?

时间:2018-10-02 23:40:02

标签: node.js mongodb express mongoose socket.io

我不确定是否存在某些我不理解的问题或某种错误,但我只是无法弄清楚。基本上,有时我会从服务器向API发送请求以获取一些信息,然后将其保存到数据库中,但是每当保存数据时,socket.io请求都会被阻塞,并且仅当所有数据都被阻塞时已更新是其他请求一堆通过时。我知道他们被阻止了,因为我试图在数据更新时每100毫秒发送一次聊天消息,并且只有当API中的最后一条信息被保存时,消息才全部通过,而消息却没有通过已保存。如何确保它不会阻止其他请求?

这是我测试时的控制台输出示例:

...
New chat message received
New chat message received
New chat message received
New chat message received
UPDATING 1455 ITEMS
UPDATED ALL PRICES, TOOK 3592
New chat message received
New chat message received
New chat message received
New chat message received
...

代码:

request('url')), (err, response, body) => {
        let items = JSON.parse(body);
        let startTime = new Date().getTime();
        console.log(`UPDATING ${items.prices.length} ITEMS`);

        for (let i = 0; i < items.prices.length; i++) {
            const item = items.prices[i];

            Prices.findOneAndUpdate({item: item.name}, {$set: {price: item.price, last_update: Date.now()}}, (err, res) => {
                if(!res){
                    newPrice = new Prices({
                        item: item.name,
                        price: item.price
                    });

                    newPrice.save((err, saved) => {
                        if (err) {
                            console.log(err);
                        }
                    })
                }

                if(i == items.prices.length - 1){
                    console.log(`UPDATED ALL PRICES, TOOK ${new Date().getTime() - startTime}`);                    
                }
            });
        }
});

不确定这是否对您有帮助,但这是处理接收消息的代码:

socket.on('sendMessage', (data) => {
    User.findOne({id: socket.request.user.id}, (err, user) => {
        if (err) throw err;

        //Check if the user is muted and if not, proceed
        if(user.mutedUntil < Date.now()){
            User.findOneAndUpdate({id: socket.request.user.id}, {$set: {lastMessageDate: Date.now()}}, (err, dbUser) => {
                if (err) throw err;

                let parsed = ParseMessage(data.message);                     

                if(parsed.command === 'none'){
                    SendMessage(dbUser, socket, data);
                }else{
                    commandData = {parsed: parsed, socket: socket}
                    ExecuteChatCommand(commandData);
                }
            });
        }else{
            socket.emit('serverMessage', {
                type: 'error',
                title: 'You\'re muted',
                message: 'You are muted and can\'t chat until ' + user.mutedUntil
            });
            console.log('Muted user tried chatting');
        }
    });       
});

1 个答案:

答案 0 :(得分:0)

您的for循环正在执行阻塞操作,因为它是同步操作。

您应该考虑改用 Promises 。与其在{6}中使用BlueBird中的for或在ES6中使用Promise.all来实现Promise.map or Promise.all循环,而是以异步的方式。

对于您的查询,您可以使用猫鼬.exec()将其转换为完整的承诺。

注意:您正在尝试查找并更新1455次for循环...也许在Bluebird中查看Promise.mapSeries,以便不会全部发送承诺同时以连续方式到达Mongo