在js asynchronus中推送数组不起作用

时间:2018-01-24 17:25:18

标签: javascript node.js express

我尝试用dirs推送用户数组。但是此后,dir属性在console.log语句中仍为空。 有想法吗?我知道我可以使用同步功能,但朋友告诉我,同步功能阻止了所有其他的事情发生。

    router.get('/', function(req, res, next) {
    const db = req.db;
    const query = "SELECT * FROM users";
    const users = [];

    db.query(query, (error, results, fields) => {
        for(let i = 0; i < results.length ; i++){
            users.push(results[i]);
            users[i].dir = [];
            fs.readdir(path.join(__dirname,'..', 'userdata', results[i].username), (err, entries) => {
                users[i].dir.push(entries[i]);
            });

        }
        console.log(users);
        res.render("admin", {
            user: req.session.user,
            dbUsers: users,
        });
    });
});

所以我刚刚更新了我的代码。但它也不起作用。

3 个答案:

答案 0 :(得分:1)

正如@jfriend00所提到的,你需要研究异步操作。

我使用promises为异步调用重构了你的代码。你可以通过使用await来使它更​​容易阅读。

const queryUsers = (db) => new Promise ((resolve, reject) => {
    const query = "SELECT * FROM users";

    db.query(query, (error, results, fields) => {
        if (error) {
            return reject(error);
        }

        resolve(results);
    });
});

const getUserFiles = username => new Promise((resolve, reject) => {
    fs.readdir(path.join(__dirname,'..', 'userdata', username), (err, entries) => {
        if (err) {
            return reject(err);
        }

        resolve(entries);
    });
});

const getUsersFiles = users => Promise.all(
    users.map(user => getUserFiles(user.username)
        .then(files => ({ ...user, dir: files })))
);

router.get('/', function(req, res, next) {
    queryUsers(req.db)
        .then(getUsersFiles)
        .then(users => {
            console.log(users);
            res.render("admin", {
                user: req.session.user,
                dbUsers: users,
            });
        });
});

答案 1 :(得分:0)

fs.readdir是异步函数,这意味着循环不会等到readdir函数完成然后继续下一次迭代,尝试使用fs.readdirSync使其同步,或者您可以使用async模块:

for(let i = 0; i < results.length ; i++){
    users.push(results[i]);

    let entries = fs.readdirSync(path.join(__dirname,'..', 'userdata', results[i].username));

    users[i].dir = entries;
}

Async module解决方案:

async.eachOf( results, function(user, i, next) {

    users.push(user);

    fs.readdir(path.join(__dirname,'..', 'userdata', user.username), (err, entries) => {

        // if error pass it to the last callback
        if (err) return next(err);

        user.dir = entries;

        // iteration done
        next();
    });


}, function (err) {

    // this function is executed only when all iteration done

    if (err) {
        throw err;
        return res.send('error occured');
    }

    res.render("admin", {
        user: req.session.user,
        dbUsers: users,
    });

});

答案 2 :(得分:-1)

你可以在这一行i中调出users[i].dir.push(entries[i]);的值吗?我猜每次都是最大编号项目+1,因为fs.readdir调用是异步的,i的值与预期的不匹配。尝试在这样的闭包中使用一个值。创建闭包时,i的值将作为idx保存到闭包中。

 for(let i = 0; i < results.length ; i++){
        (idx => {
            users.push(results[idx]);
            users[idx].dir = [];
            fs.readdir(path.join(__dirname,'..', 'userdata', results[i].username), (err, entries) => {
                users[idx].dir.push(entries[idx]);
            });
        })(i);
 }