簡體   English   中英

Javascript承諾和遞歸:這是堆棧炸彈嗎?

[英]Javascript promises and recursion: is this a stack bomb?

我對Java相對較新,對Promise及其范圍有點困惑。

假設我有以下方法:

function fetchAllData(){
    //Calling backend to fetch data, returns a promise
    backend.getMoreData(localData.length, 1000).then(function(data){
        //Store fetched data
        for(let i = 0; i < data.length; i++){
            localData.push(data[i]);
        }

        //If there's more data, invoke fetchData() again
        if(data.length > 0){
            log("Fetching more data...");
            fetchAllData();
        } else{
            log("Fetched all data!");
        }
    } );
}

基本上,該方法是這樣運行的:

  1. 從后端API獲取一些數據(該API返回承諾)
  2. 兌現承諾后,數據將添加到本地變量
  3. 如果要提取的數據更多,則以遞歸方式調用該函數以提取更多的數據,直到已提取所有數據

我的問題是:這是潛在的“堆棧炸彈”嗎? 或者,由於應允機制,在調用“ then()”方法之前從堆棧中彈出了調用函數?

我問是因為我看到的內存使用率超出預期,並且使用該方法時某些瀏覽器崩潰,這幾乎使我懷疑各種data實例在整個鏈完成之前是否不會被取消分配

編寫遞歸異步函數沒有錯。 但是,讓我們退后一步,問兩個重要的問題:

  1. 您如何知道何時安全讀取全局localData
  2. backend.getMoredata如何知道如何獲取“下一個”數據? 即,是什么阻止它重復第一個查詢?

要回答1,我們必須等到獲取最后一個數據,然后最終解決最后一個Promise –正是在這一點上,我們知道我們擁有所有數據。

要回答2,您可能正在使用另一個未包含在代碼粘貼中的全局變量。 但總的來說,您將希望避免在代碼中引入新的全局變量。 相反...

使用功能參數! 我們通過添加可選參數並定義默認值來解決這兩個問題。 現在, localData實際上是本地數據 ,很明顯backend.getMoreData如何查詢“下一個”數據塊

const fetchAll = (page = 0, localData = []) =>
  backend.getMoreData(page).then(data =>
    data.page === data.pageCount
       ? localData
       : fetchAll(page + 1, localData.concat(data.results)))

這是一個完整的演示。 我刪掉了backend和一個DB常量,因此我們可以看到它在成功和錯誤情況下都可以正常工作

 const DB = { 0: { results: [ 'a', 'b', 'c' ], page: 1, pageCount: 3 } , 1: { results: [ 'd', 'e', 'f' ], page: 2, pageCount: 3 } , 2: { results: [ 'g' ], page: 3, pageCount: 3 } } const backend = { getMoreData: page => DB[page] === undefined ? Promise.reject(Error(`Data not found`)) : Promise.resolve(DB[page]) } const fetchAll = (page = 0, localData = []) => backend.getMoreData(page).then(data => data.page === data.pageCount ? localData : fetchAll(page + 1, localData.concat(data.results))) // query all data starting on page 0 fetchAll().then(console.log, console.error) // [ 'a', 'b', 'c', 'd', 'e', 'f' ] // query all data starting on page 5 (out of bounds) fetchAll(5).then(console.log, console.error) // Error: Data not found 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM