2017-09-20 91 views
0

我得到一個引發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

這看起來像一個電話被用作錘。當然,更好的解決方案是等待設置'user.orderData.pendingItem'的任何內容完成。至少,爲此增加一些延遲。 –

+0

即使你得到這個工作,你基本上做了'while(true)',但遞歸。無論在何處填充「pendingItem」,都會更好,然後在代碼中可以解決它。這樣你就不會在等待完成時創建一個調用堆棧。 –

+0

@ug_我同意您的評論。然而,我目前的問題是所有的數據都被存儲在內存中,而'user'或'orderData'實際上應該存儲在一個數據庫中,以便我可以在查詢上放置一個承諾。但是,我幾乎堅持到我獲得批准才能繼續使用數據庫。 – user3593810

回答

2

理想情況下,你應該聽一些事件,而不是投票,但在認識到這是一個臨時的解決辦法...

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); 
     }); 
    }); 
} 
相關問題