承诺的新意,想学习。 我有这一系列的shopIds:
let shopIdsArray = ['shop1','shop2','shop3'];
和外部承诺电话
getProducts(shopId, 'products') //promise returns the products of this shop
不幸的是,承诺不会返回shopId,只返回产品,因此我必须以某种方式保留shopId并在承诺完成后将其与产品一起存储。 我目前的做法是用每个shopId调用promise,并将每个promise调用的结果添加到storesAndProductsArray中,如下所示:
shopsAndProductsArray.push({
"id":shopId,
"products":products
});
稍后,我的“包装承诺”应该返回已完成的商店和产品阵列。
我当前的代码(节点,ES6)如下所示:
updateProducts = new Promise(
function (resolve, reject) {
let shopIdsArray = ['shop1','shop2','shop3'];
const shopsAndProductsArray = [];
let promisesArray = [];
shopIdsArray.forEach((shopId) => {
let promise = getProducts(shopId, 'products')
.then((products) => {
const shopInfoObject = {
"id":shopId,
"products":products
};
console.log("sio: ",shopInfoObject); //prints shopIds and products fine.
shopsAndProductsArray.push(shopInfoObject);
promisesArray.push(promise);
});
});
Promise.all(promisesArray)
.then(function (shopsAndProductsArray) {
resolve(shopsAndProductsArray); //the shopsAndProductsArray is undefined?
});
}
);
在解析时,shopsAndProductsArray是......不为空,但由与shopIdsArray相同数量的条目组成,但数组项未定义。我可能应该首先将promises放入数组中,然后在Promise.all中对它们进行处理,但在那时我丢失了对promise所属的商店ID的引用。
我阅读了许多关于迭代和承诺的其他例子,并尝试了许多其他方法,但似乎我还没有完全理解在哪一点上被称为什么。我确定以我的方式填充promises数组是错误的,但我不知道如何调用Promise.all。
我想我可以将问题缩小到:
提前感谢您的帮助。
编辑: 非常感谢justelouise和Felix Kling。我知道我的事情过于复杂,但无法将我的手指放在哪里。由于你的例子,我现在明白了我所缺少的东西。 我认为你的答案基本上是平等的并且都得到了彻底解释我给justelouise提供了接受复选标记,因为她似乎是第一名,而Felix Kling的名声稍微有点O_o。
答案 0 :(得分:1)
我认为你可以简化你的功能:
return Promise.all(shopIdsArray.map(shopId => {
return getProducts(shopId).then((products) => {
return {
id: shopId,
products,
};
});
}));
Promise.all 返回一个promises数组,当你通过map函数迭代到数组时,在每个商店id执行 getProducts 调用。返回产品数据后,您仍然可以访问相应的商店ID,并返回包含ID和结果的新对象
return {
id: shopId,
products,
};
最后,Promise.all返回一个数组,其中包含在其中执行的每个promise的返回值。
答案 1 :(得分:1)
您的代码可以简化为:
updateProducts = Promise.all(
['shop1','shop2','shop3'].map(
id => getProducts(id, 'products').then(products => ({id, products}))
)
);
这与你的方法完全相同,只是不那么冗长。
由于Promise.all
已经返回了一个承诺,因此无需在其周围添加new Promise(...)
。
如果要将数组的每个元素转换为其他元素,则Array#map
是一种更有用的方法。它将传递的回调应用于数组的每个元素,并返回其返回值的数组。在您的情况下,您想为每个商店ID创建一个Promise,这就是
['shop1','shop2','shop3'].map(id => getProducts(id, 'products'))
确实
现在,既然你不仅想获得产品而且还要获得ID,我们必须稍微修改一下getProducts
的结果,这就是
.then(products => ({id, products}))
一样。这没什么特别的。我们只返回一个包含两个属性id
和products
的对象,而不仅仅是products
数组。
使用Promise.all
和Array#map
,您无需“手动”跟踪承诺(promisesArray
)和结果(shopsAndProductsArray
)。