Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

An apply function for synchronous tasks #208

Closed
sfrdmn opened this Issue · 9 comments

3 participants

@sfrdmn

Just an idea. Seems to me like it might be useful to add another apply method which creates a continuation function around a synchronous task. This is useful if you have a mix of synchronous and asynchronous tasks that need to be run in series. Being that synchronous tasks don't generally take callbacks, this saves programmers the time and mess of wrapping the task themselves.

async.series([

  ...
  async.applySync(task, args...),
  ...

], function() { ... });

Where applySync returns a function equivalent to

function(callback) {
  task(args... );
  callback();
}

Would be happy to do a pull request if it's wanted :)

@brianmaissy

@sfrdmn, sounds like a great idea to me! Still want to do it or should I?

@caolan
Owner

Change callback(); to async.nextTick(callback); so that it actually runs asynchronously too please :) - not sure if applySync is a good name or not, but I'm struggling to think of a better one. I like the idea in principle though :+1:

@brianmaissy

I think applySync is a pretty good name.

It's always going to be a little clumsy because the name 'apply' is already confusing for something which does something very different than Function.prototype.apply.

But given that name, if async.apply(fs.writeFile, 'testfile1', 'test1') means "create a continuation function which applies the asynchronous function fs.writeFile to the given arguments", then async.applySync(fs.writeFileSync, 'testfile1', 'test1') means "create a continuation function which applies the synchronous function fs.writeFileSync to the given arguments".

@caolan
Owner

Oh, and let's wrap the task function call in a try/catch so we can pass errors back to the callback too.

@brianmaissy

I don't understand why you need async.nextTick(callback). Either way the task itself runs synchronously, all that happens in the call to callback() is informing async that it has finished. Why does it matter if that happens on the same tick the task finishes or on the next one?

@sfrdmn

I'm also unclear on this. But it seems as though all synchronous tasks are handled in a similar way throughout the code. In until for example, if the previous iteration completed synchronously, the next one will be deferred with nextTick. I'm guessing that's to yield CPU time to other tasks after a potentially lengthy, synchronous task? It also prevents a bunch of synchronous tasks from stacking up and creating this huge blocking series of tasks.

Though, that all seems to be handled already in the rest of the code, so maybe it's redundant to include it here? But no, I guess including it guarantees the same "callback on nextTick" functionality, even when the method is used outside of other async methods. And also, it wouldn't make any sense to use an applySync method just to run some synchronous tasks in order, so it seems reasonable that synchronous tasks are handled as such. That is, in accordance with the fact that they're probably running "alongside" some asynchronous tasks.

Yeah, so I'll give the pull a shot :)

@sfrdmn sfrdmn referenced this issue from a commit in sfrdmn/async
@sfrdmn sfrdmn Added applySync method. Issue: caolan/async#208 e1490e0
@sfrdmn

I'll also add documentation in a bit.

@brianmaissy

I hereby revoke my question on why nextTick is necessary. After studying another issue (215, but I don't want to semantically reference it) I now understand it.

@sfrdmn, you are correct that in the case of whilst and until, there is an issue of blocking. Explicitly deferring until the next rotation of the event loop is how it allows other things to keep processing while it's checking, without setting a timeout.

But in this case, it's not a matter of performance or blocking, since the callback is just called once to let async know that the task is done. Here it's a matter of control flow. In most usages it makes no difference, but as you correctly stated, we want to conform to the convention that callbacks are invoked asynchronously.

@sfrdmn

I hereby added some documentation : )

Woops, looks like I forgot to create a topic branch. Hopefully that's not a problem...

@caolan caolan closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.