Then After forEach

twitter logo github logo ・1 min read

Hi. I need a function to make sure forEach is completed in JavaScript.

Simply I created this function;

Object.defineProperty(Array.prototype, "asyncForEach", {
    enumerable: false,
    value: function(task){
        return new Promise((resolve, reject) => {
            this.forEach(function(item, index, array){
                task(item, index, array);
                if(Object.is(array.length - 1, index)){
                    resolve({ status: 'finished', count: array.length })
                }
            });        
        })
    }
});

I use this function like below;


homePage.disabled = true

orders.asyncForEach(function (order) {
    api.sendOrder(order)
}).then(function (data) {
    homePage.disabled = false
})

This function works as I expect.

So friends, do you know any other ways? Is this an optimized way to catch async operations are completed?

twitter logo DISCUSS (4)
markdown guide
 
const orderPromises = orders.map(order => api.sendOrder(order));
Promise.all(orderPromisses).then(arrayOfResponses => {
    // do your stuff
})

You have over overengineered this and your solution wasn't really working as it should.

 

Yes, This is definitely the solution! Node has native support for dealing with multiple async promises.

You could even remove the variable assignment (though JS is going to assign it to a temp anyways);


return Promise.all(orders.map(api.sendOrder))
  .then(allOrders => {
    ...
  });

Thats if sendOrder does not need its functional context. Semantically the same solution, though.

 

I've come up with this solution:

(async () => {
    const fetch = (name, time) => new Promise(resolve => setTimeout(resolve, time, name))
    const orders = [fetch('order1', 500), fetch('order2', 700), fetch('order3', 1000), fetch('order4', 1200)];

    orders[Symbol.asyncIterator] = async function * () {
        yield * [...this];
    }

    for await (const resolvedOrder of orders) {
        console.log(resolvedOrder)
    }

    console.log('finished !')
    /*
    order1
    order2
    order3
    order4
    finished!
    */
})()

I wouldn't say your approach is not optimized, it looks fine to me. I have to mention that I'm not very experienced though, so I'm not sure my opinion is 100% accurate.

I hope this was helpful to you in some way.

 

With MojiScript I have created an async map, filter and reduce to make things like this cake.

import map from 'mojiscript/list/map'

const sleep = timeout => new Promise(resolve => setTimeout(resolve, timeout))

const array = [ 1, 2, 3 ]

const asyncTransform = async x => {
  await sleep(1000)
  return x * 2
}

map (asyncTransform) (array) //=> Promise ([ 2, 4, 6 ])

Check it out here: mojiscript.js.org/#/list-map

Also related: Why async code is so damn confusing (and a how to make it easy)

Classic DEV Post from Jun 14 '18

Negotiating is hard.

It was a delight to chat about job offers and negotiating with Gloria Kimbwala and Jessica Rose!

Ali GOREN profile image
I'm a front-end developer. I'm living in Turkey. I started my professional career in 2016. I also interest in Backend, SQL technologies.

Customize your DEV feed to keep up with the frameworks and languages you care about.

Get Started