Рекурсивное обещание: RangeError: Превышен максимальный размер стека вызовов.
Я получаю RangeError: Превышен максимальный размер стека вызовов
function getUser(userId) {
return new Promise((resolve, reject) => {
controller.storage.users.get(userId, function(err, user) {
if (err) reject(err);
if (user) {
if(!(user.orderData.pendingItem)) {
getUser(userId)
}
else {
resolve(user.orderData.pendingItem);
}
}
})
})
};
Дилемма, с которой я сталкиваюсь, заключается в том, что всякий раз, когда я бегу controller.storage.users.get
он не всегда сразу разрешает все свойства и значения пользовательского объекта, поэтому я пытаюсь запустить его снова, если orderData.pendingItem
не там.
Тем не менее, я думаю, потому что он запускается так много раз, что вызывает ошибку стека вызовов.
Какой лучший способ подойти к этому или решить эту проблему?
1 ответ
В идеале вы должны прислушиваться к какому-то событию, а не к опросу, но при том понимании, что это временное решение...
new Promise()
запускает свой конструктор синхронно и может показаться, что controller.storage.users.get()
также выполняет свой обратный вызов синхронно. Возможность "Превышен максимальный размер стека вызовов" может быть исключена путем принудительного рекурсивного getUser()
вызов должен быть сделан асинхронно, и самый простой способ сделать это состоит в цепочке new Promise().then(/* recurse from here */)
,
function getUser(userId) {
return new Promise((resolve, reject) => {
controller.storage.users.get(userId, function(err, user) {
if (err) reject(err);
if (!user) reject(new Error('no user for id: ' + useId)); // this branch needs to be catered for
resolve(user); // make `user` available to the .then() below
});
}).then(function(user) {
return (user.orderData && user.orderData.pendingItem) || getUser(userId); // compact and safe
});
}
Это должно сработать, но без защиты "Максимальный размер стека вызовов" дает хорошие шансы на то, чтобы сработать один или два процессора без веской причины.
Как указано в комментариях выше, вы можете и, вероятно, должны добавить некоторую задержку в рекурсию:
function delay(t) {
return new Promise(function(resolve) {
setTimeout(resolve, t);
});
}
function getUser(userId) {
return new Promise((resolve, reject) => {
controller.storage.users.get(userId, function(err, user) {
if (err) reject(err);
if (!user) reject(new Error('no user for id: ' + useId)); // this branch needs to be catered for
resolve(user); // make `user` available to the .then() below
});
}).then(function(user) {
return (user.orderData && user.orderData.pendingItem) || delay(200).then(function() { // adjust the delay to maximum acceptable value
return getUser(userId);
});
});
}