admin管理员组

文章数量:1278854

New to promises, would like to learn. I have this array of shopIds:

let shopIdsArray = ['shop1','shop2','shop3'];

and an external promise call

getProducts(shopId, 'products') //promise returns the products of this shop

Unfortunately, the promise does not return the shopId, just the products, so I have to somehow keep the shopId and store it together with the products once the promise is finished. My current approach is to call the promise with each shopId, and add the result of each promise call to a shopsAndProductsArray like this:

shopsAndProductsArray.push({
    "id":shopId,
    "products":products
}); 

Later on, my "wrapper promise" should return the finished shopsAndProductsArray.

My current code (node, ES6) looks like:

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?
            });
    }
);

On resolve, the shopsAndProductsArray is...not empty, but consists of the same number of entries as the shopIdsArray, but the array items are undefined. I probably should put the promises into an array first, then work on them in Promise.all, but at that point I lost the reference to which shop id the promise belongs.

I read many other examples about iteration and promises and tried many other ways but it seems that I haven't fully understood what is called at which point. I'm sure filling the promises array the way I do is wrong, but I had no better idea how to invoke Promise.all.

I think I could narrow my questions down to:

  1. How should I iterate over the shopIds, calling the promise with each?
  2. How can I preserve the shopId once a promise returns a list of products?
  3. How can I return the array of shopIds and products once all shopIds have been processed?

Thanks in advance for any help.

EDIT: Thank you so much, justelouise and Felix Kling. I knew I was overplicating things, but couldn't put my finger where. I understand now what I was missing, thanks to your examples. I think your answers are essentially equal and both thoroughly explained. I give the accept checkmark to justelouise because she appears to be first and Felix Kling has slightly more reputation O_o.

New to promises, would like to learn. I have this array of shopIds:

let shopIdsArray = ['shop1','shop2','shop3'];

and an external promise call

getProducts(shopId, 'products') //promise returns the products of this shop

Unfortunately, the promise does not return the shopId, just the products, so I have to somehow keep the shopId and store it together with the products once the promise is finished. My current approach is to call the promise with each shopId, and add the result of each promise call to a shopsAndProductsArray like this:

shopsAndProductsArray.push({
    "id":shopId,
    "products":products
}); 

Later on, my "wrapper promise" should return the finished shopsAndProductsArray.

My current code (node, ES6) looks like:

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?
            });
    }
);

On resolve, the shopsAndProductsArray is...not empty, but consists of the same number of entries as the shopIdsArray, but the array items are undefined. I probably should put the promises into an array first, then work on them in Promise.all, but at that point I lost the reference to which shop id the promise belongs.

I read many other examples about iteration and promises and tried many other ways but it seems that I haven't fully understood what is called at which point. I'm sure filling the promises array the way I do is wrong, but I had no better idea how to invoke Promise.all.

I think I could narrow my questions down to:

  1. How should I iterate over the shopIds, calling the promise with each?
  2. How can I preserve the shopId once a promise returns a list of products?
  3. How can I return the array of shopIds and products once all shopIds have been processed?

Thanks in advance for any help.

EDIT: Thank you so much, justelouise and Felix Kling. I knew I was overplicating things, but couldn't put my finger where. I understand now what I was missing, thanks to your examples. I think your answers are essentially equal and both thoroughly explained. I give the accept checkmark to justelouise because she appears to be first and Felix Kling has slightly more reputation O_o.

Share Improve this question edited Oct 13, 2017 at 6:47 user1840267 asked Oct 13, 2017 at 5:34 user1840267user1840267 4281 gold badge6 silver badges20 bronze badges 7
  • You are calling shopsAndProductsArray.push(exchangeInfoObject); but the object you create is assigned to shopInfoObject. – Felix Kling Commented Oct 13, 2017 at 5:42
  • All your promises resolve to undefined - because your .then(products => does not return anything ... which is why shopsAndProductsArray is an array of undefined function (shopsAndProductsArray) – Jaromanda X Commented Oct 13, 2017 at 5:43
  • note : your const shopsAndProductsArray = []; is never used for anything – Jaromanda X Commented Oct 13, 2017 at 5:45
  • by the way - excluding console.logging, var updateProducts = Promise.all(['shop1', 'shop2','shop3'].map(id => getProducts(id, 'products').then(products => ({id, products})))); is probably what you wanted – Jaromanda X Commented Oct 13, 2017 at 5:53
  • @Felix, I corrected the code. – user1840267 Commented Oct 13, 2017 at 6:48
 |  Show 2 more ments

2 Answers 2

Reset to default 11

I think you can simplify your functions as such:

return Promise.all(shopIdsArray.map(shopId => {
  return getProducts(shopId).then((products) => {
    return {
      id: shopId,
      products,
    };
  });
}));

Promise.all returns an array of promises created as you are iterating thru the array via the map function where in getProducts call is executed for each shop id. Once the products data is returned, you still have access with the corresponding shop id for it and return a new object consisting of the id and the results

return {
  id: shopId,
  products,
};

Lastly, Promise.all returns an array containing the returned value for each promise executed within it.

Your code can be simplified a lot to:

updateProducts = Promise.all(
  ['shop1','shop2','shop3'].map(
    id => getProducts(id, 'products').then(products => ({id, products}))
  )
);

It's exactly the same approach as yours, just less verbose.

Since Promise.all already returns a promise, there is no need to put a new Promise(...) around it.

If you want to convert every element of an array to something else, then Array#map is a more useful method. It applies the passed callback to every element of the array and returns an array of its return values. In your case you want to create a Promise for each shop ID, and that's what

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

does.

Now, since you do not just want to get the products but also the ID, we have to modify the result of getProducts a little bit, which is what the

.then(products => ({id, products}))

does. There is nothing really special about this. We simply return an object with the two properties id and products instead of just the products array.

With Promise.all and Array#map you don't need to "manually" keep track of the promises (promisesArray) and the results (shopsAndProductsArray).

本文标签: javascriptPromisesall with additional valuesStack Overflow