Javascript 承诺。都有附加价值

Javascript 承诺。都有附加价值,javascript,node.js,promise,es6-promise,Javascript,Node.js,Promise,Es6 Promise,初学承诺,愿意学习。 我有一组ShopID: let shopIdsArray = ['shop1','shop2','shop3']; 还有一个外部承诺电话 getProducts(shopId, 'products') //promise returns the products of this shop 不幸的是,承诺不返回shopId,只返回产品,因此我必须以某种方式保留shopId,并在承诺完成后将其与产品一起存储。 我目前的方法是使用每个shopId调用promise,并将每个p

初学承诺,愿意学习。 我有一组ShopID:

let shopIdsArray = ['shop1','shop2','shop3'];
还有一个外部承诺电话

getProducts(shopId, 'products') //promise returns the products of this shop
不幸的是,承诺不返回shopId,只返回产品,因此我必须以某种方式保留shopId,并在承诺完成后将其与产品一起存储。 我目前的方法是使用每个shopId调用promise,并将每个promise调用的结果添加到ShopAndProductsArray,如下所示:

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…不是空的,但包含与ShopIdArray相同数量的条目,但数组项未定义。我可能应该先将承诺放入数组,然后在Promise.all中处理它们,但在那一点上,我丢失了承诺所属的商店id的引用

我阅读了许多关于迭代和承诺的其他例子,并尝试了许多其他方法,但似乎我还没有完全理解在哪一点上被称为什么。我确信用我的方式填充promises数组是错误的,但我不知道如何调用Promise.all

我想我可以把我的问题缩小到:

  • 我应该如何迭代ShopID,使用 每个人
  • 一旦承诺返回产品列表,我如何保存shopId
  • 处理完所有ShopID后,如何返回ShopID和产品的数组
  • 提前感谢您的帮助

    编辑: 非常感谢你,justelouise和Felix Kling。我知道我把事情搞得太复杂了,但我不能把我的手指放在哪里。多亏了你们的例子,我现在明白我遗漏了什么。
    我认为你的答案基本上是一样的,而且都解释得很透彻。我给justelouise打上“接受”复选标记,因为她似乎是第一个,而Felix Kling的声望稍高一些。

    我认为您可以简化您的功能:

    return Promise.all(shopIdsArray.map(shopId => {
      return getProducts(shopId).then((products) => {
        return {
          id: shopId,
          products,
        };
      });
    }));
    
    Promise.all返回一个Promise数组,当您通过map函数在数组中进行迭代时,会对每个店铺id执行in-getProducts调用。返回产品数据后,您仍然可以使用相应的店铺id访问该产品,并返回一个由id和结果组成的新对象

    return {
      id: shopId,
      products,
    };
    

    最后,Promise.all返回一个数组,其中包含在其中执行的每个Promise的返回值。

    我认为您可以将函数简化为:

    return Promise.all(shopIdsArray.map(shopId => {
      return getProducts(shopId).then((products) => {
        return {
          id: shopId,
          products,
        };
      });
    }));
    
    Promise.all返回一个Promise数组,当您通过map函数在数组中进行迭代时,会对每个店铺id执行in-getProducts调用。返回产品数据后,您仍然可以使用相应的店铺id访问该产品,并返回一个由id和结果组成的新对象

    return {
      id: shopId,
      products,
    };
    

    最后,Promise.all返回一个数组,其中包含在其中执行的每个Promise的返回值。

    您的代码可以简化为:

    updateProducts = Promise.all(
      ['shop1','shop2','shop3'].map(
        id => getProducts(id, 'products').then(products => ({id, products}))
      )
    );
    
    这和你的方法完全一样,只是没有那么冗长

    由于
    Promise.all
    已经返回了一个承诺,因此没有必要在其周围添加
    新承诺(…)

    如果要将数组的每个元素转换为其他元素,则
    array#map
    是一种更有用的方法。它将传递的回调应用于数组的每个元素,并返回其返回值的数组。在您的案例中,您希望为每个店铺ID创建一个承诺,这就是为什么

    ['shop1','shop2','shop3'].map(id => getProducts(id, 'products'))
    
    是的

    现在,由于您不仅要获取产品,还要获取ID,我们必须稍微修改
    getProducts
    的结果,这就是

    .then(products => ({id, products}))
    
    是的。这没什么特别的。我们只返回一个具有两个属性
    id
    products
    的对象,而不仅仅是
    products
    数组


    使用
    Promise.all
    Array#map
    您不需要“手动”跟踪承诺(
    promisesArray
    )和结果(
    shopsAndProductsArray
    )。

    您的代码可以简化为:

    updateProducts = Promise.all(
      ['shop1','shop2','shop3'].map(
        id => getProducts(id, 'products').then(products => ({id, products}))
      )
    );
    
    这和你的方法完全一样,只是没有那么冗长

    由于
    Promise.all
    已经返回了一个承诺,因此没有必要在其周围添加
    新承诺(…)

    如果要将数组的每个元素转换为其他元素,则
    array#map
    是一种更有用的方法。它将传递的回调应用于数组的每个元素,并返回其返回值的数组。在您的案例中,您希望为每个店铺ID创建一个承诺,这就是为什么

    ['shop1','shop2','shop3'].map(id => getProducts(id, 'products'))
    
    是的

    现在,由于您不仅要获取产品,还要获取ID,我们必须稍微修改
    getProducts
    的结果,这就是

    .then(products => ({id, products}))
    
    是的。这没什么特别的。我们只返回一个具有两个属性
    id
    products
    的对象,而不仅仅是
    products
    数组


    使用
    Promise.all
    Array#map
    您不需要“手动”跟踪承诺(
    promisesArray
    )和结果(
    shopsAndProductsArray
    )。

    您正在调用
    shopsAndProductsArray.push(ExchangeInfo对象)
    但是您创建的对象被分配给
    shopInfoObject
    。您所有的承诺都被解析为
    未定义的
    ,因为您的
    。然后(products=>
    不会返回任何内容…这就是为什么
    shopsAndProductsArray
    是一个未定义的
    函数数组(shopsAndProductsArray)
    注意:你的
    const shopsAndProductsArray=[];
    从来没有被用于任何东西——除了console.logging,
    var updateProducts=Promise.all(['shop1','shop2','shop3'].map(id=>getProducts(id,'products')。然后(products=>({id,products})));
    可能就是你想要的wanted@Felix,我更正了代码。您正在呼叫
    shopsAndProductsA