Skip to content

Add asyncify method to make async versions of synchronous methods #806

Closed
@cappslock

Description

@cappslock

Composing sync and async methods gets a little hairy. Consider a case where you're performing a waterfall of some methods, but one in the middle is synchronous. You have to do something like this:

async.waterfall(
    [
        asyncMethod1,
        asyncMethod2,
    ]
    function (error, data) {
        if (error) {
            // handle error
        }
        else {
            var nextData = syncMethod3(data);
            async.waterfall(
                [
                    async.apply(asyncMethod4, data),
                    asyncMethod5
                ],
                function (error, data) {
                    if (error) {
                        // handle error, probably in the same way as before
                    }
                    else {
                        doSomething(data);
                    }
                }
            );
        }
    }
);

I think this could be improved with the addition of a simple asyncify method. This method could take a synchronous function as an argument and return an asynchronous version. The returned function would invoke the original function or caught errors to the callback. Here is a naive implementation:

function asyncify (fn) {
    return function () {
        var callback = arguments[fn.length]
        try {
            var returnValue = fn.apply(null, Array.prototype.slice.call(arguments, 0, fn.length));
            setImmediate(function () {
                callback(null, returnValue);
            });
        }
        catch (e) {
            return callback(e);
        }
    }
}

With this, we can clean up the original code significantly:

async.waterfall(
    [
        asyncMethod1,
        asyncMethod2,
        async.asyncify(syncMethod3),
        asyncMethod4,
        asyncMethod5
    ],
    function (error, data) {
        if (error) {
            // handle error
        }
        else {
            doSomething(data);
        }
    }
)

Could something like this be added as an async method?

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions