Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stop execution flow #1035

Closed
simoneb opened this issue Feb 24, 2016 · 10 comments
Closed

stop execution flow #1035

simoneb opened this issue Feb 24, 2016 · 10 comments
Labels

Comments

@simoneb
Copy link

simoneb commented Feb 24, 2016

I know this has been asked before, like in #11. I would like to open a discussion about a way to early interrupt any of the collections or flow utilities or provide a new utility for that purpose.

I often find myself needing to execute several asynchronous operations (usually in series, but the same would apply to a parallel scenario) until one of them returns a result.

I would normally implement this using series or waterfall, except that I would like to exit early and avoid running the following operations in the chain.

Also, I would like to avoid having to signal an error to do that, which I would then have to analyze specifically in the final callback to check whether it is a legitimate error or the special chain-breaking error.

@aearly
Copy link
Collaborator

aearly commented Feb 24, 2016

We're going to add async.race #1018 soon. Would this work for your use case? Otherwise you have to break the execution flow with a fake error object.

@simoneb
Copy link
Author

simoneb commented Feb 25, 2016

The semantics are not quite the same. I would like to avoid executing the other functions as soon as one returns a value, or not start them at all.

@aearly
Copy link
Collaborator

aearly commented Mar 6, 2016

We don't have a good way to break execution. You can do something like this:

function doSomethingAsync(options, callback) {
  async.waterfall([
    function step1(taskCb) {
      // do something
    },
    function step2(result, taskCb) {
      if (someCondition()) {
        // exit early
        return callback();
      }

      // continue on
      taskCb(null, result);
    },
    task3
  ], callback)
}

This will prevent task3 from running, but waterfall will wait forever for task2 to call the taskCb, causing a small memory leak. A way around this is to still call the task callback with a fake error:

function doSomethingAsync(options, callback) {
  var stop = {};
  async.waterfall([
    function step1(taskCb) {
      // do something
    },
    function step2(result, taskCb) {
      if (someCondition()) {
        // exit early
        callback();
        // use a fake error
        return taskCb(stop);
      }

      // continue on
      taskCb(null, result);
    },
    task3
  ], function (err, result) {
    if (err === stop) {
      // it was the fake error as we break out of the waterfall, ignore
      return;
    }
    callback(err, result);
  });
}

It's a bit clunky through.... I don't have any good ideas on how to officially support this. Maybe something like taskCb(async.BREAK_SENTINEL) that is handled internally automatically?

@simoneb
Copy link
Author

simoneb commented Mar 6, 2016

What about an additional optional callback function passed to all tasks which, if called, immediately stops execution and runs the final callback?

@aearly
Copy link
Collaborator

aearly commented Mar 6, 2016

It would be hard to differentiate that extra callback arg from the regular callback arg. Is the second-to last arg a normal parameter, or the callback?

@simoneb
Copy link
Author

simoneb commented Mar 7, 2016

Good point. I have no other ideas.

@aearly
Copy link
Collaborator

aearly commented Mar 9, 2016

Related: #552

We need a way to flush the rest of the tasks when you exit early.

@aearly
Copy link
Collaborator

aearly commented Mar 22, 2016

Closing this in favor of #1064

@aearly aearly closed this as completed Mar 22, 2016
@wood1986
Copy link

What about my proposal

@aearly
Copy link
Collaborator

aearly commented Aug 1, 2016

We're going to use an explicit false value to signal an early exit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants