Поиск мангуста происходит после вызова res.render ()? - PullRequest
0 голосов
/ 11 июня 2018

Я пытаюсь написать "клон Facebook" в nodejs с mongoDB.Проблема, с которой я сталкиваюсь, заключается в том, что каждый раз, когда пользователь заходит в профиль пользователя, ему нужно получить массив своих друзей.то, как я это делаю, выглядит следующим образом:

router.get("/user/:id/profile", isLoggedIn, (req, res) => {
let friends = [];
User.findById(req.params.id, (err, user) => {
    if (err) {
        req.flash("error", "There has been an error going to this persons profile.");
        res.redirect("back");
    } else {
        if (user.friends.length > 0) {
            for(var i = 0; i < user.friends.length; i++) {
                User.findById(user.friends[i], (err, friend) => {
                    if (err) {
                        console.log(err);
                        req.flash("error", "Could not find the friends list")
                        res.redirect("back")
                    } else {
                        friends.unshift({
                            firstName: friend.firstName,
                            lastName: friend.lastName,
                            _id: friend._id
                        })
                        console.log(friends)
                    }
                });
            }
            console.log(friends, "158")
            res.render("user", { userData: user, friends: friends })
        } else {
            // render the page without the friends array.
            res.render("user", { userData: user }); // im calling it userData because i have a local template variable called user and i don't want to over-write it
        }
    }
});
});

и что происходит, когда я выполняю console.log (friends) внутри цикла for, я получаю массив друзей, в котором все правильно, но когда я делаю console.log (friends) перед res.render ("user"), массив становится пустым.есть идеи почему?

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Это из-за асинхронного характера узла.Использование res.render внутри вашей функции обратного вызова или использование обещаний поможет разобраться в этом.

Без обещаний

User.findById(req.params.id, (err, user) => {
if (err) {
    req.flash("error", "There has been an error going to this persons profile.");
    res.redirect("back");
} else {
    if (user.friends.length > 0) {
        for(var i = 0; i < user.friends.length; i++) {
            User.findById(user.friends[i], (err, friend) => {
                if (err) {
                    console.log(err);
                    req.flash("error", "Could not find the friends list")
                    res.redirect("back")
                } else {
                    friends.unshift({
                        firstName: friend.firstName,
                        lastName: friend.lastName,
                        _id: friend._id
                    })
                    console.log(friends)
                    res.render("user", { userData: user, friends: friends })
                }
            });
        }
        console.log(friends, "158")

    } else {
        // render the page without the friends array.
        res.render("user", { userData: user }); 
    }
}
});

С обещанием

User.findById(user.friends[i])
.then((friend) => {
     friends.unshift({
        firstName: friend.firstName,
        lastName: friend.lastName,
        _id: friend._id
    })
})
.then(()=>{
    res.render("user", { userData: user, friends: friends })
})
.catch( err=>{
    console.log(err);
    req.flash("error", "Could not find the friends list")
    res.redirect("back")
})

---- РЕДАКТИРОВАТЬ ----

Теперь можно использовать асинхронное ожидание.Я не показал это здесь.

Тот, который я написал без обещаний, не будет работать .Для выполнения с / без обещания вам нужно использовать рекурсивный способ синхронизации вместо цикла for.

0 голосов
/ 11 июня 2018

При написании кода для node.js вам нужно привыкнуть к асинхронным функциям, так как МНОГИЕ дополнения / классы / код используют это.

Кодирование больше не является «линейным», но функции вызываются, как только будет выполнен предыдущий код.

В вашем случае findById запускает процесс поиска документов в mongoDB и, как только он их найдет, он вызовет (в вашем случае анонимную) функцию обратного вызова с параметрами (err, friend).

Ваш вызов res.render находится за пределами этого обратного вызова и будет немедленно вызван после запуска findById.Это рано.
Вам нужно поместить свой res.render в обратный вызов, чтобы получить данные обратно.

РЕДАКТИРОВАТЬ: следующий код не будет работать должным образом из-за цикла.Нам нужно использовать обещания, как показано в ответе Prajvals.Пожалуйста, используйте его второй пример, так как он работает.

User.findById(user.friends[i], (err, friend) => {
    if (err) {
        console.log(err);
        req.flash("error", "Could not find the friends list")
        res.redirect("back")
    } else {
        friends.unshift({
            firstName: friend.firstName,
            lastName: friend.lastName,
            _id: friend._id
        })
        console.log(friends);
        res.render("user", { userData: user, friends: friends })
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...