Search code examples
javascriptsynchronizationstratifiedjs

StratifiedJS: how call modules from .js files


I'm using the library StratifiedJS (http://onilabs.com/stratifiedjs) to construct an api database synchronous.

But I am confused about how to include files.

As the documentation says, I import the library this way:

<script type="text/javascript" src="js/stratified.js" main="js/index.sjs"></script>

My index.sjs file have this code:

db = require("mongo");
var data = db.find({collection: "itens"});

Thi find method in the module mongo has this code:

exports.find = function(params) {

    waitfor(var rows) { 
        $.getJSON("db/find", params, function(result){      
            resume(result.rows);
        }); 
    }

    return rows;
}

When I access the db module through file index.sjs or via a script inside a tag:

<script type="text/sjs"> ... code .. </ script>

the code works perfectly. But when I try to access through a file of type "text/javascript" behavior changes.

In this case if I run the code below into a file .js:

var data = db.find({collection: "itens"});

The data variable will not contain the returned data from base, beacause the code return rows; runs before the getJSON callback function to be executed;

My question is: how do I then run the modules declared in sjs files in the javascript file type.


Solution

  • The issue here is that normal JS cannot block and wait for asynchronous results in the same way that stratified JS can (which is of course the reason why we have SJS in the first place!)

    So when you have a stratified function that does something asynchronous and you call it from a normal JS function, then the latter will not 'see' the actual value of the stratified function, but a kind-of 'continuation' object.

    JS cannot really do anything with this continuation object, so the idea is that a typical SJS program would have stratified top-level code that calls other stratified or non-stratified code, but that you never (or rarely) call stratified from non-stratified code.

    If you really need to call stratified from 'normal' non-stratified code you can arrange for stratified functions to take an optional callback argument:

    // SJS file:
    exports.find = function(params, callback) { 
      waitfor (var rows) { ... }
    
      if (callback) 
        callback(rows);
      else
        return rows;
    }
    

    .

    // called from SJS:
    var data = db.find({collection:'items'});
     ... use data ...
    

    .

    // called from JS:
    db.find({collection:'items'}, function(data) { ... use data ... });
    

    Alternatively you can wrap the SJS function with 'deferred' (https://conductance.io/reference#sjs:function::deferred) and then handle the result with a callback in JS:

    // SJS file:
    exports.find = function(params) { ... };
    
    exports.deferredFind = require('sjs:function').deferred(exports.find);
    

    .

    // JS file:
    ...
    db.deferredFind({collection: 'items'}).then(function(data) { ... });