2017-10-09 38 views
1

需要與承諾相關的幫助。請參考以下詳細信息,題目是更多的理論,我不明白,我應該用什麼流程:在承諾內部爲每個異步請求做些什麼?

  1. 我們異步功能getDataFromUri(),它返回的數據,其被過濾,並保存到ARR的對象,讓它命名爲res;
  2. 對於數組res中的每個活動(對象),我希望發送異步請求,這會將產品的活動圖像存儲到對象。因此,我應該有一個數組res存儲所有過濾的數據(活動名稱,活動圖像);

我需要不便等:

[{ 
    name: "Somename", 
    images: ['uri', 'uri', 'uri', 'uri', 'uri', 'uri'] 
},{ 
    name: "Somename", 
    images: ['uri', 'uri', 'uri', 'uri', 'uri', 'uri'] 
} 
] 
  • 請在RES陣列一些其他動作。
  • 這個函數獲取活動:

    function getDataFromUri(uri) { 
        return new Promise((resolve, reject) => { 
        request.get(uri, (err, res, body) => { 
        if(err || res.statusCode !== 200) { 
         reject(handleErr(err)); 
        } else { 
         resolve(body); 
        } 
        }); 
    }); 
    } 
    

    這個函數獲取運動圖像:

    function getProductsOfCampaign(id) { 
        var productsImagesLinks = []; 
        return new Promise((resolve, reject) => { 
        getDataFromUri(`SOME_URI/${id}.json`) 
         .then((json) => { 
         var productsList = JSON.parse(json).products; 
         resolve (productsList.map((product) => product.imgSrc)); 
         }).catch((e) => { 
         throw new Error(e); 
         }) 
        }); 
    } 
    

    在這裏,我遇到了問題:

    getDataFromUri(someLink) //Get campaings; 
        .then((result) => { 
    
        //NOT WORKING FOREACH 
    
        result.forEach((item, i) => { 
         item.images = getProductsOfCampaign(item.id); 
        }) 
    
        return result; 
        }) 
        .then((result) => { 
        //Do something else to array with images; 
        }); 
    
    1. 我怎麼能強迫接下來是forE ach .then()表達式等待所有圖像URL被保存?
    2. 我試了Promise.all(),但似乎缺乏如何正確實現它的知識。

    如果您能幫我解決這個問題,我將非常感激。謝謝。

    +0

    不知道,如果它是一個重複的。但是這裏我的答案](https://stackoverflow.com/a/43766002/157247)展示瞭如何做到這一點,你是否想這樣做串聯或平行。 –

    +0

    您可以嘗試使用[Promise.all()](https://developer.mozilla。org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all),可能會改變你的一些邏輯。 – eventHandler

    +0

    這是因爲'.forEach'沒有返回值,所以你需要使用'.map',它可以返回一些東西(承諾)等待。 –

    回答

    2

    觀察到:

    1. itemforEach是一個副本。
    2. getProductsOfCampaign返回一個Promise
    3. 網絡是一種盡力服務。

    這樣做:

    getDataFromUri(someLink) // Get campaigns 
        .then(result => { 
    
        var promises = result.map(item => 
         getProductsOfCampaign(item.id) 
         .then(products => { 
          item.images = products; 
          return item; 
         }) 
         // 3: Best-effort service 
         .catch(() => {}) 
        ); 
    
        return Promise.all(promises); 
        }).then(items => { 
    
        console.log(items); 
        // Do something else to array of items with images 
        }); 
    

    其他讀者可以測試的正確性與此:

    function getDataFromUri(someLink) { 
        return new Promise((resolve) => { 
        setTimeout(resolve, 1000, [{id: 1}, {id: 2}]); 
        }) 
    } 
    
    function getProductsOfCampaign(id) { 
        return new Promise((resolve) => { 
        setTimeout(resolve, 1000, id * id); 
        }) 
    } 
    
    var someLink = ''; 
    

    由於本傑明Gruenbaum的提示.catch(() => {})可以Promise.all使用爲盡力而爲的服務。

    +1

    這只是在Promise中重新實現異步信號.all –

    +0

    錯誤。 'Promise.all'不是最好的。 – aaron

    +0

    Pfft,那麼只需執行'.catch((=)=> {})'並且擁有你的「盡力而爲」的語義,這種語義在某種程度上是不錯的。 –

    0
    let campaigns = null; 
    getDataFromUri(someLink) //Get campaings; 
    .then((result) => { 
        campaigns = result; 
    
        let pImages = [] 
        result.forEach((item, i) => { 
        pImages.push(getProductsOfCampaign(item.id)); 
        }); 
    
        return Promise.all(pImages); 
    }) 
    .then((images) => { 
        campaigns.forEach((campaign, index) => { 
        campaign.images = images[index]; 
        }); 
    
        // ... Do something else to array with images; 
    });