У меня проблема с манипулированием глобальным массивом.
Код работает хорошо, если он написан так
function getChatBox(originMessage) {
return new Promise((resolve, reject) => {
resolve(
Message.aggregate([
{
$match: { _id: originMessage }
},
{
$unwind: "$subMessages"
},
{
$lookup: {
from: "messages",
localField: "subMessages",
foreignField: "_id",
as: "chained"
}
},
{
$unwind: "$chained"
},
{
$project: { chained: 1, _id: 0 }
}
])
);
});
}
let chatBoxes = [];
if (user.messages.length > 0) {
user.messages.forEach(async msg => {
//let chatBox = await getChatBox(msg.originMessage);
//chatBoxes.push(chatBox);
//chatBoxes.push(await getChatBox(msg.originMessage));
chatBoxes.push("cool");
console.info(chatBoxes);
});
}
console.info("outer", chatBoxes);
И результат такой, когда он работает
Однако как только я добавляю строку кода (для извлечения данных из базы данных), доза глобального массива не меняется.
между ** ** - добавленная строка кода (let chatBox = await getChatBox (msg.originMessage);):
function getChatBox(originMessage) {
return new Promise((resolve, reject) => {
resolve(
Message.aggregate([
{
$match: { _id: originMessage }
},
{
$unwind: "$subMessages"
},
{
$lookup: {
from: "messages",
localField: "subMessages",
foreignField: "_id",
as: "chained"
}
},
{
$unwind: "$chained"
},
{
$project: { chained: 1, _id: 0 }
}
])
);
});
}
let chatBoxes = [];
if (user.messages.length > 0) {
user.messages.forEach(async msg => {
**let chatBox = await getChatBox(msg.originMessage);**
//chatBoxes.push(chatBox);
//chatBoxes.push(await getChatBox(msg.originMessage));
chatBoxes.push("cool");
console.info(chatBoxes);
});
}
console.info("outer", chatBoxes);
И вывод показывает это: Я не знаю, почему порядок смены логов
Пожалуйста, помогите мне понять, что происходит. Я хочу вставить в глобальный массив (chatBoxes) полученные данные, но за пределами функции массив все еще пуст (не пуст, если я добавлю в функцию простую строку).
Я подозреваю, что код после forEach запускается до того, как завершит цикл. Может в этом проблема?
Спасибо !
Ваша переменная chatBox объявляется с помощью оператора let
, тогда chekBox будет доступен только в его области (анонимная функция внутри user.message.forEach()
.
Измените let
с помощью оператора var
, и если checkBox является глобальной переменной, было бы лучше объявить его вне области действия forEach()
, возможно, в верхней части function getChatBox()
Спасибо, но это не сработало. Поменял на var. chatBoxes уже находится за пределами forEach. Когда выборка происходит каким-то образом, глобальная переменная изменяется только внутри forEach, а затем за ее пределами значение массива такое же, как оно было инициировано. Также он изменяет порядок журналов, он пропускает код внутри forEach, а затем запускает его.
Это потому, что вы повторно объявляете checkBox с помощью «let checkBox» внутри forEach (), это вопрос указателя (невидимого для программиста с javascript). Я думаю, будет работать, если вы отключите оператор let внутри forEach ()
Я изменил его, но он не работает :( Переменная chatBox - это единственный элемент, который я хочу поместить в массив chatBoxes.
Можете ли вы поделиться данными, представленными originMessage, чтобы четко подтвердить свой код? Иначе я не смогу тебе помочь.
Конечно, originMessage - это идентификатор документов сообщений в mongoDB (например: ObjectId ("5bd33cce32b3e62d1450aa12")). Сообщения источника - это первые отправленные сообщения. каждое ответное сообщение на исходное сообщение имеет идентификатор originMessage в своем документе.
Я создал своего рода ваш пользовательский объект, но код работает, только если я уберу ключевое слово "await" перед getChatBox (msg.originMessage). Это странно. Кстати без await "chatBox (результат getChatBox ()) является объектом обещаний, но пустым {} ... У вас такая же ошибка?
Что такое Message.aggregate ()? Может быть, будет лучше, если вы дадите мне хотя бы одно из значений, возвращаемых Message.aggregate (), потому что целью этого потока является не Message.aggregate. В любом случае мы близки
Я починил это. Я пока не знаю, как это сделать. Я использую обычный цикл for вместо forEach. appernatly использование async / await внутри forEach не работает. Я узнаю об этом. Подробнее читайте здесь: https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404
Если вы можете, отредактируйте ваш фактический код как текст в своем вопросе - изображения кода в одиночестве - это утомительно и сложно для работы и отладки. Это заставляет тех, кто иначе хотел бы помочь вам, сначала сделать расшифруйте ваше изображение, что является пустой тратой времени.