Nodejs 异步的问题 用数组保存json数据 死活都保存不进去

Nodejs 异步的问题 用数组保存json数据 死活都保存不进去

app.get(’/homepage/:user’,function(req,res){
var lessoninfoarray = {};
var classarray = [];
User.find({username:req.params.user},function(err,doc){
if(doc.length!=0){
UC.find({ userid:doc[0].id },function(err,docs){
if(docs.length!=0){
for(var j=0;j<docs.length;j++){
Class.findById(docs[j].classid,function(err,classinfo){
classarray.push(classinfo);
});	
}
console.log(“classarray is :”+classarray); // 这里是空
res.render(‘homepage’,{title:‘homepage’,classinfodoc:JSON.stringify(classarray)});	
}else{
res.render(‘homepage’,{title:‘homepage’,classinfodoc:[]});
}
});

	}else{
		res.redirect('/register');
		}	
	});

});


6 回复

Node.js 异步的问题:用数组保存 JSON 数据时无法成功保存

在使用 Node.js 处理异步操作时,经常会遇到数组无法按预期填充数据的情况。这通常是由于对异步操作的误解导致的。在你的例子中,Class.findById 是一个异步操作,而你试图在所有异步操作完成之前就访问 classarray 数组。

示例代码及解释

为了确保所有的异步操作都完成后再处理 classarray,我们可以使用 Promise.all 来等待所有的异步操作完成。

const express = require('express');
const User = require('./models/User'); // 假设这是用户模型
const UC = require('./models/UC');     // 假设这是关联模型
const Class = require('./models/Class'); // 假设这是班级模型

const app = express();

app.get('/homepage/:user', function(req, res) {
    User.findOne({ username: req.params.user })
        .then(doc => {
            if (!doc) {
                return res.redirect('/register');
            }

            return UC.find({ userid: doc.id });
        })
        .then(docs => {
            if (docs.length === 0) {
                return res.render('homepage', { title: 'homepage', classinfodoc: [] });
            }

            const promises = docs.map(doc => 
                Class.findById(doc.classid).exec()
            );

            return Promise.all(promises);
        })
        .then(classarray => {
            console.log("classarray is :" + classarray);
            res.render('homepage', { title: 'homepage', classinfodoc: JSON.stringify(classarray) });
        })
        .catch(err => {
            console.error(err);
            res.status(500).send('Server error');
        });
});

module.exports = app;

解释

  1. User.findOne: 查找用户信息。
  2. UC.find: 根据用户 ID 查找关联信息。
  3. Promise.all: 确保所有的 Class.findById 操作都完成后才继续执行。
  4. res.render: 渲染页面并将数据传递给前端。

通过这种方式,我们确保了所有的异步操作都在渲染页面之前完成,从而避免了数组未填充完整的问题。


       for(var j=0;j<docs.length;j++){
                        Class.findById(docs[j].classid,function(err,classinfo){
                            classarray.push(classinfo);
                        });    
                    }
      console.log("classarray is :"+classarray); // 这里是空

哥,push是回调里执行的,这里要用async,enventproxy之类的流程控制才方便,不要受同步编程的影响

大兄弟啊 !!给个例子吧 我被折磨疯了

没例子就不明白就先了解了解javascript的异步到底是啥意思吧。要不你要例子会要疯的。

你过个5秒,在console里查看一下classarray的内容。 你现在的console.log早了点。

你的问题出在异步操作上。Class.findById 是一个异步操作,当你调用 console.log("classarray is :" + classarray);res.render 时,Class.findById 的回调函数可能还没有执行完毕,因此 classarray 仍然是空的。

为了解决这个问题,你可以使用 async/await 或者 Promise.all 来确保所有的异步操作完成后再进行后续处理。这里提供一个使用 async/await 的示例代码:

const async = require('async');

app.get('/homepage/:user', async function (req, res) {
    try {
        const user = await User.findOne({ username: req.params.user });
        if (!user) {
            return res.redirect('/register');
        }

        const ucDocuments = await UC.find({ userid: user.id });

        if (ucDocuments.length === 0) {
            return res.render('homepage', { title: 'homepage', classinfodoc: [] });
        }

        const classPromises = ucDocuments.map(uc => Class.findById(uc.classid));
        const classInfos = await Promise.all(classPromises);

        console.log("classarray is :" + JSON.stringify(classInfos)); // 现在应该不是空

        res.render('homepage', { title: 'homepage', classinfodoc: JSON.stringify(classInfos) });
    } catch (err) {
        console.error(err);
        res.status(500).send('Server error');
    }
});

在这个例子中,我们使用了 async/awaitPromise.all 来确保所有异步操作完成后才继续执行后续逻辑。这样可以保证 classarray 在渲染页面之前已经被正确填充。

回到顶部