Skip to content

Instantly share code, notes, and snippets.

@anvk
Last active October 11, 2023 09:02
Show Gist options
  • Save anvk/5602ec398e4fdc521e2bf9940fd90f84 to your computer and use it in GitHub Desktop.
Save anvk/5602ec398e4fdc521e2bf9940fd90f84 to your computer and use it in GitHub Desktop.
Sequential execution of Promises using reduce()
function asyncFunc(e) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(e), e * 1000);
});
}
const arr = [1, 2, 3];
let final = [];
function workMyCollection(arr) {
return arr.reduce((promise, item) => {
return promise
.then((result) => {
console.log(`item ${item}`);
return asyncFunc(item).then(result => final.push(result));
})
.catch(console.error);
}, Promise.resolve());
}
workMyCollection(arr)
.then(() => console.log(`FINAL RESULT is ${final}`));
@dnaicker
Copy link

dnaicker commented May 6, 2018

reducing example to nearest simplest form:

[1,2,3].reduce((promise,item) => {
	return promise.then(() => { 
		return new Promise((resolve, reject)=> {
			resolve(item);
		})
	})
},Promise.resolve())

@hipstersmoothie
Copy link

hipstersmoothie commented Jun 1, 2018

await array.reduce(async (promise, item) => {
  await promise;
  return asyncFunction(item);
}, true);

@bradennapier
Copy link

bradennapier commented Aug 16, 2018

I know the goal is to use reduce/be functional here but just to point out using async function and a loop to make sure it works the same way Promise.all does in the end with how it resolves

async function resolveSequentially(arr) {
  const results = [];
  for (const v of arr) {
    if (typeof v === 'function') {
      results.push(await v());
    } else {
      results.push(await v);
    }
  }
  return results;
}

or the reduce parallel

function resolveSequentially(arr) {
  let r = Promise.resolve();
  return Promise.all(
    arr.reduce((p, c) => {
      r = r.then(() => (typeof c === 'function' ? c() : c));
      p.push(r);
      return p;
    }, []),
  );
}

@schmax-max
Copy link

it's friday 4:50pm and this came in at the perfect time. thank you so much!!

@printernet
Copy link

Hey seriously. Echoing the above thanks!

@empz
Copy link

empz commented Dec 1, 2018

Using reduce for this makes it harder than it has to be. It's not very easy on the eyes and mind.
I'd prefer something like this if await / async is available.

// functions is an array of functions that return a promise.
async function runInSequence(functions) {
  const results = [];

  for (const fn of functions) {
    results.push(await fn());
  }

  return results;
}

And we can use it like this:

function promisedFunction(delay, value) {
  return new Promise(resolve => {
    setTimeout(() => resolve(value), delay);
  });
}

console.time("execution");
const results = await runInSequence([
  promisedFunction.bind(this, 1000, 1),
  promisedFunction.bind(this, 1000, 2),
  promisedFunction.bind(this, 1000, 3)
]);

console.timeEnd("execution"); // execution: 3000 ms (approx)
console.log(results); // [1, 2, 3]

@robertoandres24
Copy link

Thanks. Helped me a lot to solution duplicate primary key constraint in save() method with Typeform. The parallel process was my issue and I changed my Promise.all( ) loop, for this fn, and it works great.

@juanccamachob94
Copy link

My pay:

class TasksService {
  static async execute(context, tasks) {
    let results = [];
     await tasks.reduce((promise, task) => {
      return promise
        .then((result) => {
          return TasksService.asyncFunc(task).then(r => {
            results.push(r.bind(context)())
          });
        })
    }, Promise.resolve());
    return results;
  }

  static asyncFunc(f) {
    return new Promise((resolve, reject) => {
      let task = f;
      let time = 0;
      if(typeof(task) !== 'function') {
        task = f.task;
        time = f.time;
      }
      setTimeout(() => resolve(task), time);
    });
  }
}

module.exports = TasksService;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment