У меня есть база данных, которая вызывает список последних сообщений. Каждое сообщение является объектом и хранится в виде массива этих объектов сообщения в chatListNew.
Каждый объект сообщения имеет свойство «from», которое является идентификатором пользователя, который его опубликовал. Что я хочу сделать, так это перебрать этот массив и добавить фактическую информацию профиля пользователя «От» в сам объект. Таким образом, когда веб-интерфейс получает информацию, он получает доступ к профилю отправителя одного конкретного сообщения в свойстве fromProfile соответствующего сообщения.
Я думал о том, чтобы пройтись по каждому из них и выполнить Обещание. Однако для каждого из них это очень дорого, если только несколько пользователей разместят сотни сообщений. Было бы более разумно запускать запрос mongoose только один раз для каждого пользователя . Поэтому я изобрел систему кеширования.
Тем не менее, я запутался в том, как хранить обещание будущего значения внутри элемента массива. Я думал, что установка «fromProfile» на ранее вызванное обещание будет магически удерживать это обещание, пока значение не будет разрешено. Поэтому я использовал Promise.all, чтобы убедиться, что все обещания были выполнены, а затем возвращены по результатам, но обещания, которые я сохранил в массивах, не были теми значениями, на которые я рассчитывал.
Вот мой код:
//chatListNew = an array of objects, each object is a message that has a "from" property indicating the person-who-sent-the-message's user ID
let cacheProfilesPromises = []; // this will my basic array of the promises called in the upcoming foreach loop, made for Promise.all
let cacheProfilesKey = {}; // this will be a Key => Value pair, where the key is the message's "From" Id, and the value is the promise retrieving that profile
let cacheProfileIDs = []; // this another Key => Value pair, which basically stores to see if a certain "From" Id has already been called, so that we can not call another expensive mongoose query
chatListNew.forEach((message, index) => {
if(!cacheProfileIDs[message.from]) { // test to see if this user has already been iterated, if not
let thisSearch = User.findOne({_id : message.from}).select('name nickname phone avatar').exec().then(results => {return results}).catch(err => { console.log(err); return '???' ; }); // Profile retrieving promise
cacheProfilesKey[message.from] = thisSearch;
cacheProfilesPromises.push(thisSearch); // creating the Array of promises
cacheProfileIDs[message.from] = true;
}
chatListNew[index]["fromProfile"] = cacheProfilesKey[message.from]; // Attaching this promise (hoping it will become a value once promise is resolved) to the new property "fromProfile"
});
Promise.all(cacheProfilesPromises).then(_=>{ // Are all promises done?
console.log('Chat List New: ', chatListNew);
res.send(chatListNew);
});
И это вывод моей консоли:
Chat List New: [ { _id: '5b76337ceccfa2bdb7ff35b5',
updatedAt: '2018-08-18T19:50:53.105Z',
createdAt: '2018-08-18T19:50:53.105Z',
from: '5b74c1691d21ce5d9a7ba755',
conversation: '5b761cf1eccfa2bdb7ff2b8a',
type: 'msg',
content: 'Hey everyone!',
fromProfile:
Promise { emitter: [EventEmitter], emitted: [Object], ended: true } },
{ _id: '5b78712deccfa2bdb7009d1d',
updatedAt: '2018-08-18T19:41:29.763Z',
createdAt: '2018-08-18T19:41:29.763Z',
from: '5b74c1691d21ce5d9a7ba755',
conversation: '5b761cf1eccfa2bdb7ff2b8a',
type: 'msg',
content: 'Yo!',
fromProfile:
Promise { emitter: [EventEmitter], emitted: [Object], ended: true } } ]
В то время как я надеялся на что-то вроде:
Chat List New: [ { _id: '5b76337ceccfa2bdb7ff35b5',
updatedAt: '2018-08-18T19:50:53.105Z',
createdAt: '2018-08-18T19:50:53.105Z',
from: '5b74c1691d21ce5d9a7ba755',
conversation: '5b761cf1eccfa2bdb7ff2b8a',
type: 'msg',
content: 'Hey everyone!',
fromProfile:
Promise {name: xxx, nickname: abc... etc} },
{ _id: '5b78712deccfa2bdb7009d1d',
updatedAt: '2018-08-18T19:41:29.763Z',
createdAt: '2018-08-18T19:41:29.763Z',
from: '5b74c1691d21ce5d9a7ba755',
conversation: '5b761cf1eccfa2bdb7ff2b8a',
type: 'msg',
content: 'Yo!',
fromProfile:
{name: xxx, nickname: abc... etc} } ]
Спасибо, ребята! Открыты для других способов достижения этого :)
Пит