<!DOCTYPE html>
<html lang='en'>
  <head>
    <meta charset='utf-8'>
    <title>synchronize.js</title>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <meta name='description' content=''>
    <meta name='author' content=''>

    <!-- Styles -->
    <link href='assets/bootstrap/css/bootstrap.css' rel='stylesheet'>
    <link href='assets/google-code-prettify/prettify.css' rel='stylesheet'>
    <link href='assets/style.css' rel='stylesheet'>

    <!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
    <!--[if lt IE 9]>
      <script src='http://html5shim.googlecode.com/svn/trunk/html5.js'></script>
    <![endif]-->
  </head>

  <body>

    <!-- <div class='navbar navbar-fixed-top'>
      <div class='navbar-inner'>
        <div class='container'>
          <a class='brand' href='#'>synchronize.js</a>
          <ul class='nav'>
            <li class='active'><a href='#'>Home</a></li>
            <li><a href='#about'>About</a></li>
            <li><a href='#contact'>Contact</a></li>
          </ul>
        </div>
      </div>
    </div> -->

    <div class='container'>

<!-- <pre class='prettyprint'>
a = function(){
  console.log('hi')
}
</pre> -->

      <div class='row'>
        <div class='offset1 span10'>

          <!-- Overview -->
          <div class='page-header'>
            <h1>
              synchronize.js
              <small>write asynchronous code as if it's synchronous</small>
            </h1>
          </div>
          <p>
            Use <code>await</code> and <code>defer</code> to execute asynchronous functions
            synchronously.
          </p>
          <p>
            Synchronize assumes node-style <code>(err, result)</code> callbacks.
            The second parameter given to the cb will be returned.
            If an error is present it will be thrown and can be intercepted by a try/catch statement.
            Multiple and named arguments are supported with <code>defers</code>.
          </p>
          <p>
            You can use the helper <code>sync(fn)</code> and it will use await/defer
            automatically.
            The helper is non-destructive and the function can still be called asynchronously
            if called with a callback.
            You can also mix it with other synchronous or asynchronous code.
          </p>
          <p>
            Use <code>await</code>/<code>defer</code> manually to get precise control or automatically to write compact and clean code.
          </p>

          <p>
            Install it with <code>npm install synchronize</code>.
          </p>

          <p>
            The project is hosted on
            <a href='http://github.com/alexeypetrushin/synchronize'>GitHub</a>.
            <br>
            You can report bugs and discuss features on the
            <a href='http://github.com/alexeypetrushin/synchronize/issues'>Issues</a> page.
          </p>

          <!-- How to use -->
          <h2>Usage patterns</h2>
          <div class='row'>
            <div class='span5'>
<pre class='prettyprint'>
data = sync.await(fs.readFile(fname, sync.defer()))
</pre>
            </div>
            <div class='span5'>
              <p>
                Use <code>await</code> and <code>defer</code> keywords by hand
                to call a function synchronously (you can make await and defer global
                to make things shorter).
              </p>
            </div>
          </div>
          <div class='row' style="margin-top: 10px">
            <div class='span5'>
<pre class='prettyprint'>
sync(fs, 'readFile')

var data = fs.readFile(fname)
fs.readFile(fname, function(err, data)){}
</pre>
            </div>
            <div class='span5'>
              <p>
                Use <code>sync()</code> to make an async function synchronize.js-aware.
                You can use it in both ways - synchronous or asynchronous.
                Basically it uses the same await/defer pattern, but automatically.
                This object form preserves context, unlike the form below.
              </p>
            </div>
          </div>
          <div class='row' style="margin-top: 10px">
            <div class='span5'>
<pre class='prettyprint'>
asyncFn = sync(asyncFn)

var data = asyncFn(input)
// You can still use the async form of this fn
var data = sync.await(asyncFn(input, sync.defer()))
asyncFn(input, function(err, data){})
</pre>
            </div>
            <div class='span5'>
              <p>
                You can use <code>sync()</code> on a bare function to return
                a synchronized version of the function. It can still be used
                in asynchronous form.
              </p>
            </div>
          </div>

          <!-- Samples -->

          <h2>Basic usage, printing content of file</h2>

          <div class='row'>
            <div class='span5'>
<pre class='prettyprint'>
var sync = require('synchronize')
var fs   = require('fs')

sync(fs, 'readFile')

sync.fiber(function(){
  var data = fs.readFile(__filename, 'utf8')
  console.log(data)

  try {
    data = fs.readFile('invalid', 'utf8')
  } catch (err) {
    console.log(err)
  }

  fs.readFile(__filename, 'utf8', function(err, data){
    console.log(data)
  })
})
</pre>
            </div>
            <div class='span5'>
              <p>
                In order to use synchronized functions and pause execution without blocking Node.js we
                need to wrap execution into a <code>Fiber</code> using <code>sync.fiber()</code>.
              </p>
              <p style="margin-top:50px">
                Inside of Fiber we can call asynchronous functions as if it's synchronous.
              </p>
              <p style="margin-top:30px">
                We can also use standard try/catch statements to catch asynchronous errors.
              </p>
              <p style="margin-top:70px">
                Or call readFile asynchronously if we wish.
              </p>
            </div>
          </div>

          <h2>Listing and printing files in directory</h2>
          <p>
            Listing content of current directory, checking if path is file and printing its content
            to console.
          </p>
          <div class='row'>
            <div class='span5'>
              <h3>Using synchronize</h3>
<pre class='prettyprint'>
var sync = require('synchronize')
var fs   = require('fs')

sync(fs, 'readdir', 'stat', 'readFile')

sync.fiber(function(){
  var i, paths, path, stat, data
  paths = fs.readdir('.')
  for(i = 0; i < paths.length; i++){
    path = paths[i]
    stat = fs.stat(path)
    if(!stat.isFile()) continue
    data = fs.readFile(path, 'utf8')
    console.log(data)
  }
})
</pre>
            </div>
            <div class='span5'>
              <h3>The same code without synchronization</h3>
<pre class='prettyprint'>
var fs = require('fs')

var printFile = function(paths, i){
  if(i >= paths.length) return
  var path = paths[i]
  fs.stat(path, function(err, stat){
    if(err) throw err
    if(stat.isFile()){
      fs.readFile(path, 'utf8', function(err, data){
        if(err) throw err
        console.log(data)
        printFile(paths, i + 1)
      })
    } else {
      printFile(paths, i + 1)
    }
  })
}

fs.readdir('.', function(err, paths){
  if(err) throw err
  printFile(paths, 0)
})
</pre>
            </div>
          </div>

          <h2>Parallel and serial operations</h2>
          <p>
            Synchronize.js can run multiple operations in parallel using
            <code>sync.parallel()</code>.
          </p>
          <div class='row'>
            <div class='span5'>
              <h3>Async operations in serial</h3>
<pre class='prettyprint'>
var sync = require('synchronize')

var read = function(a, cb) {
  setTimeout(function(){
    // remember that callbacks expect (err, result)
    cb(null, a)
  }, 1000)
}

// We can use the `sync` helper here to avoid using
// `await()` and `defer()` manually.
read = sync(read);

sync.fiber(function() {
  var results = []
  results.push(read(1)))
  results.push(read(2)))
  // results now contains [1,2]
})
</pre>
            </div>
            <div class='span5'>
              <h3>Async operations in parallel</h3>
<pre class='prettyprint'>
var sync = require('synchronize')

function read(a, cb) {
  setTimeout(function(){
    cb(null, a)
  }, 1000)
}

// Runs in parallel
sync.fiber(function() {
  sync.parallel(function() {
    // You must call defer() manually within
    // a parallel operation.
    read(1, sync.defer())
    read(2, sync.defer())
  });
  var results = sync.await()
  // results now contains [1,2]
});
</pre>
            </div>
          </div>

          <h2>Multiple arguments in callbacks</h2>
          <p>
            Synchronize.js accepts multiple arguments in callbacks using <code>sync.defers()</code>.
          </p>
          <div class='row'>
            <div class='span5'>
              <h3>Multiple arguments in serial</h3>
<pre class='prettyprint'>
var sync = require('synchronize')

function read(a, b, c, cb) {
  setTimeout(function(){
    cb(null, a, b, c)
  }, 1000)
}

sync.fiber(function() {
  // Returns [1,2,3]
  var results = sync.await(
    read(1, 2, 3, sync.defers()))
  // Returns {a: 4, b: 5, c: 6}
  var namedResults = sync.await(
    read(4, 5, 6, sync.defers('a', 'b', 'c')))
})
</pre>
            </div>
            <div class='span5'>
              <h3>Multiple arguments in parallel</h3>
<pre class='prettyprint'>
var sync = require('synchronize')

function read(a, b, c, cb) {
  setTimeout(function(){
    cb(null, a, b, c)
  }, 1000)
}

sync.fiber(function() {
  sync.parallel(function(){
    read(1, 2, 3, sync.defers())
    read(4, 5, 6, sync.defers())
  });
  // returns [[1,2,3],[4,5,6]]
  var results = sync.await()
  // concat to get [1,2,3,4,5,6]
  results = [].concat.apply([], results)
})
</pre>
            </div>
          </div>


          <h2>Usage with Express.js</h2>
          <div class='row'>
            <div class='span5'>
<pre class='prettyprint'>
var sync    = require('synchronize')
var fs      = require('fs')
var express = require('express')

sync(fs, 'readFile')

var app = express.createServer()
app.use(function(req, res, next){
  sync.fiber(next)
})

app.get('/', function(req, res){
  var data = fs.readFile(__filename, 'utf8')
  res.send(data, {'Content-Type': 'text/plain'})
})

app.listen(3000)
</pre>
            </div>
            <div class='span5'>
              <p>Synchronized code can be mixed with asynchronous code in any combination.</p>
              <p>
                Here is one possible way to use it with Express.js.</p>
            </div>
          </div>

          <h2>Usage with Mocha.js</h2>
          <div class='row'>
            <div class='span5'>
<pre class='prettyprint'>
var sync  = require('synchronize')
var fs    = require('fs')

sync(fs, 'readFile')

var async = sync.asyncIt

describe('File System', function(){
  it('should read file', async(function(){
    var data = fs.readFile(__filename, 'utf8')
  }))
})
</pre>
            </div>
            <div class='span5'>
              <p>
                You can use the <code>sync.asyncIt</code> helper to greatly simplify writing
                asynchronous tests.
              </p>

              <p>
                You may also take a look at
                <a href='https://github.com/alexeypetrushin/mongo-lite/blob/master/test/collection.coffee'>
                  this real-life test scenario</a>
                that uses synchronize to simplify asynchronous calls for MongoDB.
              </p>
            </div>
          </div>

          <!-- How to use -->
          <h2>Similar tools</h2>
          <p>
            <a href="http://monojs.org">MonoJS</a> - synchronous web framework based on synchronize.
          </p>

          <hr/>

          <p>Copyright <a href='http://petrush.in'>Alexey Petrushin</a>, released under MIT License</p>
        </div>
      </div>

    </div><!-- /container -->

    <a href='http://github.com/alexeypetrushin/synchronize'><img style='position: absolute; top: 0; right: 0; border: 0; z-index: 2080;'  src='https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png' alt='Fork me on GitHub'></a>

    <!-- Scripts -->
    <script src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'></script>
    <script src='assets/bootstrap/js/bootstrap.js'></script>
    <script src='assets/google-code-prettify/prettify.js'></script>
    <script>
      $(prettyPrint)
    </script>
  </body>
</html>