Как указал Берги, ошибка будет выглядеть как connect
, которая возвращает обещание , которое вы вообще не выполняете, в том числе не дожидаетесь его завершения.Таким образом, как минимум, вам нужно справиться с этим:
const connectionPromise = mongoose.connect(dbUrl, { useNewUrlParser: true })
.catch(error => {
// Handle connection error
});
Затем в addUserToLeague
:
const addUserToLeague = (userId, leagueId) => {
return connectionPromise.then(connection => {
// ...logic here
});
};
... но , я спрашиваю васдолжно быть подключено, когда модуль загружен таким образом, а не передавать соединение в addUserToLeague
.
Помимо этого, фактическое использование Promise.all
в порядке, но:
- Можно надеяться, что
findById
не разрешит обещание с ложным значением, если элемент не найден, так что весь первый обработчик then
кажется ненужным. - Предположительно
save
возвращает обещание.Вы не обрабатываете отклонение или не ждете разрешения тех, кто так. - Я бы использовал деструктуризацию, чтобы избежать
arr[0]
и arr[1]
, так как заказ легко забыть. - Нет никакой причины, чтобы обработчик
then
с вызовами push
был отделен от обработчика then
, выполняющего сохранение. addUserToLeague
должен возвращать результат цепочки обещаний, так что вызов кодаэто A) Знает, когда оно закончено, и B) Знает, когда оно терпит неудачу. - Ошибки не должны обрабатываться в
addUserToLeague
;вместо этого обработайте их в вызывающей стороне. - Существует также проблема, заключающаяся в том, что данные денормализованы : вы храните информацию о членстве как в пользовательском объекте, так и вобъект лиги.Может быть, это относительно нормально для баз данных документов (я бы не знал);в СУБД вы бы хранили информацию в одноместном месте.Причина ясна из кода в
addUserToLeague
: что делать, если сохранение пользователя происходит успешно, но сохранение лиги не удается?Затем пользовательский объект говорит, что он является членом лиги, а объект лиги не говорит, что он является членом.Также существует проблема, заключающаяся в том, что, поскольку она хранится в двух местах, даже если ничего не происходит неправильно, в течение короткого периода один из (пользователь или лига) будет сохранен, а другой - нет.Оба являются проблемами целостности.Если вы можете нормализовать хранение этой информации в одном месте, это было бы хорошо.Если вы не можете это сделать, вам нужно обновить код, чтобы он сохранил один из них, дождался его успешного выполнения, сохранил другой, а в случае неудачи попытается отменить изменение первого.
Примерно так (я не пытаюсь решить проблему нормализации здесь, это большая картина):
const
mongoose = require('mongoose'),
User = require('./models/users'),
League = require('./models/leagues'),
dbUrl = process.env.DBURL || 'mongodb://localhost/predictor';
const addUserToLeague = (connection, userId, leagueId) => {
return Promise.all([
User.findById(userId),
League.findById(leagueId)
])
.then(([user, league]) => {
user.leagueMemberships.push(league);
league.users.push(user);
return Promise.all([user.save(), league.save()]);
})
.then((([user, league]) => {
console.log(`User ${user._id} added to league ${league._id}`);
});
};
mongoose.connect(dbUrl, { useNewUrlParser: true })
.then(connection => addUserToLeague(connection, process.argv[2], process.argv[3]) // Needs 2 args: User ID and League ID
.catch(error => {
// Handle/report error
});
Если вы используете какой-либо недавний вариант Node, вы можете использовать async
функция:
const
mongoose = require('mongoose'),
User = require('./models/users'),
League = require('./models/leagues'),
dbUrl = process.env.DBURL || 'mongodb://localhost/predictor';
const addUserToLeague = async (connection, userId, leagueId) => {
let [user, league] = await Promise.all([
User.findById(userId),
League.findById(leagueId)
]);
user.leagueMemberships.push(league);
league.users.push(user);
[user, league] = await Promise.all([user.save(), league.save()]);
console.log(`User ${user._id} added to league ${league._id}`);
};
mongoose.connect(dbUrl, { useNewUrlParser: true })
.then(connection => addUserToLeague(connection, process.argv[2], process.argv[3]) // Needs 2 args: User ID and League ID
.catch(error => {
// Handle/report error
});