Проблема в том, что когда вы рекурсивно вызываете getNextUsername()
, вы не разрешаете самое внешнее Обещание. Этот вызов вызовет новое Обещание и (возможно), которое будет разрешено, но значение не будет go нигде, поскольку оно не используется.
Так как getNextUsername()
производит Обещание и он (надеюсь) разрешается со значением, вы можете очень просто изменить свой код, добавив шаг разрешения:
const getNextUsername = () => {
return new Promise((res, rej) => {
Counter.findByIdAndUpdate('usernames', {
$inc: {
sequence: 1
}
}, {
upsert: true,
new: true
}, (err, result) => {
if (err) rej(err);
User.findOne({
username: result.sequence
}, (err, u) => {
if (err) rej(err);
if (u) {
//after the recursive call completes, resolve with the returned value or fail if it failed
getNextUsername()
.then(res)
.catch(rej);
} else {
res(result.sequence);
}
})
})
})
}
Таким образом, когда последующее Обещание будет разрешено, вы будете распространять разрешенное значение из Обещания. Независимо от того, сколько у вас обещаний, это должно работать, даже если у вас есть Promise1 -> Promise2 -> Promise3, когда третий разрешается, второй затем вызовет .then(res)
и вернет значение, которое снова вызовет .then(res)
в первое Promise и pu sh значение out.
.catch(rej)
будет делать то же самое, но с ошибками - если какое-либо внутреннее обещание не будет выполнено, все те, что находятся наверху, потерпят неудачу.
Вот очень простая реализация рекурсивных функций с использованием Promises просто для иллюстрации идеи:
function recursiveSum(a, b, debugPrefix = ">") {
return new Promise((res, rej) => {
console.log(debugPrefix, "recursively summing", a, b);
if (b <= 0) {
console.log(debugPrefix, "result found");
res(a);
} else {
console.log(debugPrefix, "going deeper");
recursiveSum(a+1, b-1, debugPrefix + ">")
.then(res);
}
})
}
recursiveSum(5, 3)
.then(console.log);
Последнее замечание: я не знаю, является ли это лучшим способом решения вашей проблемы. Я не знаком с MongoDB, возможно, есть лучшие подходы. Мое решение - просто исправить текущий код.