2017-10-09 94 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; 
    });