1

I am trying to execute following array (avoid callbackHell) of functions(sync/async), in a sequential order, implementing function runCallbacksInSequence (I need to implement my own function to understand how callbacks work and avoid using Async.js).

I do not quite understand how callbacks work that is why I am doing this exercise. Here is what I have so far. The function runCallbacksInSequence works well but I am having hard time to implement callback (null, result) signature. At the moment it follows callback (result) signature.

If you have any ideas let me know what I am doing wrong and how I can fix it.
- no promises and async/await

function first(cb) {
  setTimeout(function() {
    console.log('first()');
    cb('one');
    // cb(null, 'one');
  }, 0);
}

function second(cb) {
  setTimeout(function() {
    console.log('second()');
    cb('two');
    // cb(null, 'two');
  }, 100);
}

function third(cb) {
  setTimeout(function() {
    console.log('third()');
    cb('three');
    // cb(null, 'three');
  }, 0);
}

function last(cb) {
  console.log('last()');
  cb('lastCall');
  // cb(null, 'lastCall');
}

function runCallbacksInSequence(fns, cb) {
  fns.reduce((r, f) => k => r(acc => f(x => k([...acc, x]))), k => k([]))(cb);
}

const fns = [first, second, third, last];

runCallbacksInSequence(fns, results => {
  console.log('-- DONE --');
  console.log(...results);
});

6
  • 2
    How about using ES6 syntax with async/await functionality? It does exactly what you need. Commented Jun 7, 2019 at 8:06
  • @Maksim no promises and async/await in this case Commented Jun 7, 2019 at 8:07
  • If you can't use Promises, I suggest using generators. Or use Babel (which will convert Promises to generators) Commented Jun 7, 2019 at 8:12
  • 1
    You can keep passing a callback to next function. Commented Jun 7, 2019 at 8:14
  • 1
    @Seblor the OP is trying to learn the pattern by implementing it. It is an exercise to learn not production code. Commented Jun 7, 2019 at 8:14

2 Answers 2

2

In your runCallbacksInSequence you first of all have to move the x to the second position, also for consistency the final callback should be called with its first argument being null:

 function runCallbacksInSequence(fns, cb) {
   //                                    v  v                                  vvvvvvvv
   fns.reduce((r, f) => k => r(acc => f((e, x) => k([...acc, x]))), k => k([]))(r => cb(null, r));
 }

If you want the first callback with an error (having the first argument set) to directly terminate the chain, you can extend your chain a bit:

 //                                              vvvvvv
 fns.reduce((r, f) => k => r(acc => f((e, x) => e ? cb(e) : k([...acc, x]))), k => k([]))(r => cb(null, r));
Sign up to request clarification or add additional context in comments.

3 Comments

does it make a difference if we use err instead of null
Yes, that ends the chain
so I have to handle the errors cause when I call it with cb(err, null) it gives me an error ReferenceError: err is not defined
1

To answer I do not quite understand how callbacks work
A callback is a function that is to be executed after another function has finished executing. For example.

function run(cb){
  console.log("run")
  cb("okay it is running");
}

A simple function that logs stuff. How do you run it?

run()

But you want to receive the callback. To know that above cb() everything was done. You do this.

run((arg) => {
  console.log(arg) //logs "okay it is running"
});

What you actually got is a "call", "back" from the function you ran, while running it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.