Skip to content

Wrappers

amaksr edited this page Jun 12, 2017 · 5 revisions

There are many functions out there that return results via callbacks. In order to use them in your nsynjs-executed code you just need to wrap them, so they would be able to post results of callback back to nsynjs, and resume execution of nsynjs engine.

Q: Wait, why would I need wrappers, if I already have promisified functions?

A: Wrappers provide some extra functionality:

  • ability to cleanup all pending callbacks in case if caller pseudo-thread is stopped externally via ctx.stop()
  • ability to handle functions that trigger unknown number of callbacks (see readline example that uses nodeReadline wrapper),
  • ability to return error instead of triggering an exception.

All nsynjs-aware wrappers should generally do following:

  • Accept reference to a current pseudo-thread as a parameter (e.g. ctx).
  • Call wrapped function
  • Return an object, and assign results of the callback to some properties of that object.
  • Call ctx.resume() in th callback of wrapped fucntion, so caller pseudo-thread will continue execution.
  • Set destructor function, that will be called in order to cancel long-running function.

Note: if wrapper may return without calling function with callback, nsynjs needs to be notified about this by calling ctx.setDoNotWait(true) right before return statement.

All nsynjs-aware wrapper should have 'nsynjsHasCallback' property set to true.

Here is an example of simple wrapper to setTimeout:

    var wait = function (ctx, ms) {
        setTimeout(function () {
            ctx.resume(); // <<-- resume execution of nsynjs pseudo-thread, referred by ctx
        }, ms);
    };
    wait.nsynjsHasCallback = true; // <<-- indicates that nsynjs should stop and wait when calling this function

Example of wrapper to setTimeout, that will be gracefully stopped in case if pseudo-thread is stopped:

    var wait = function (ctx, ms) {
        var timeoutId = setTimeout(function () {
            console.log('firing timeout');
            ctx.resume();
        }, ms);
        ctx.setDestructor(function () { // <<-- this function will be called in case if pseudo-thread is requested to stop
            console.log('clear timeout');
            clearTimeout(timeoutId);
        });
    };
    wait.nsynjsHasCallback = true;

Note: if wrapper may return without calling function with callback, nsynjs needs to be notified about this by calling ctx.setDoNotWait(true) right before return statement:

    var wait = function (ctx, ms, condition) {
        if(condition) {
            ctx.setDoNotWait(true); // <-- function with callback is not going to be called by wrapper,
                                    // therefore caller may continue execution
            return;
        }
        var timeoutId = setTimeout(function () {
            console.log('firing timeout');
            ctx.resume();
        }, ms);
        ctx.setDestructor(function () {
            console.log('clear timeout');
            clearTimeout(timeoutId);
        });
    };
    wait.nsynjsHasCallback = true;

See wrappers/nodeReadline.js for example of wrapper with conditional callbacks.

Example of wrapper to jQuery's getJSON, that can return data or throw an exception back to nsynjs-executed code:

    var ajaxGetJson = function (ctx,url) {
        var res = {}; // <<-- results will be posted back to nsynjs via method to this object
        var ex; // <<-- possible exception
        $.getJSON(url, function (data) {
            res.data = data; // <<-- capture data from callback, or
        })
        .fail(function(e) {
            ex = e; // <<-- capture exception
        })
        .always(function() {
            ctx.resume(ex); // <<-- resume pseudo-thread
        });
        return res;
    };
    ajaxGetJson.nsynjsHasCallback = true; // <<-- indicates that nsynjs should stop and wait on evaluating this function

Wrappers for some common functions could be found in /wrappers folder. See JSDOCs.

Clone this wiki locally