Рекурсивное обещание: 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);
        });
    });
}
Другие вопросы по тегам