From c1a4c2834991e1226f4f215852bd50d9af76791b Mon Sep 17 00:00:00 2001 From: Joongi Kim Date: Tue, 5 Apr 2016 00:01:31 +0900 Subject: [PATCH] Added loopUntilNoMoreEvents() API to wait for aribtrary code. * Existing APIs rely on explicit callback argument or predicate. This API does not require such prior information, just like how the node.js main loop continues or terminates. * To use this API to block for a specific region of code, you should take care of other existing callbacks using unref() and ref() methods to prevent them from making loopUntilNoMoreEvents() to block "longer" than you want. --- index.js | 36 ++++++++++++++++++++++-------------- src/deasync.cc | 5 +++-- test.js | 20 +++++++++++++++++--- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/index.js b/index.js index 5166550..24377df 100644 --- a/index.js +++ b/index.js @@ -5,17 +5,17 @@ * Copyright 2014-2015 Abbr * Released under the MIT license */ - + (function () { - + var fs = require('fs'), path = require('path'), binding; - + // Seed random numbers [gh-82] if on Windows. See https://github.com/laverdet/node-fibers/issues/82 if(process.platform === 'win32') Math.random(); - - + + // Look for binary for this platform var nodeV = 'node-' + /[0-9]+\.[0-9]+/.exec(process.versions.node)[0]; var nodeVM = 'node-' + /[0-9]+/.exec(process.versions.node)[0]; @@ -50,27 +50,35 @@ function cb(e, r) { err = e; res = r; - done = true; + done = true; } } } - + module.exports = deasync; - + module.exports.sleep = deasync(function(timeout, done) { setTimeout(done, timeout); }); - + module.exports.runLoopOnce = function(){ process._tickDomainCallback(); binding.run(); }; - + + module.exports.loopUntilNoMoreEvents = function(){ + var more = false; + do { + process._tickDomainCallback(); + more = binding.run(); + } while (more); + }; + module.exports.loopWhile = function(pred){ - while(pred()){ - process._tickDomainCallback(); - if(pred()) binding.run(); - } + while(pred()){ + process._tickDomainCallback(); + if(pred()) binding.run(); + } }; }()); diff --git a/src/deasync.cc b/src/deasync.cc index ccb37c6..cc7f06b 100644 --- a/src/deasync.cc +++ b/src/deasync.cc @@ -6,8 +6,9 @@ using namespace v8; NAN_METHOD(Run) { Nan::HandleScope scope; - uv_run(uv_default_loop(), UV_RUN_ONCE); - info.GetReturnValue().Set(Nan::Undefined()); + bool _more = uv_run(uv_default_loop(), UV_RUN_ONCE); + v8::Local more = Nan::New(_more); + info.GetReturnValue().Set(more); } static NAN_MODULE_INIT(init) { diff --git a/test.js b/test.js index fa4ca1c..74effed 100644 --- a/test.js +++ b/test.js @@ -21,11 +21,25 @@ var request = deasync(function (url, done) { }).on('error', done); }); - +// Expected order: "1st", "2nd", "3rd", "4th" +var sleep_without_cb_or_pred = function (timeout) { + setTimeout(function() { console.log('2nd'); }, timeout); +}; +var t = setTimeout(function () { + console.log('4th'); +}, 2000); +t.unref(); // should not make loopUntilNoEvents() to block +console.log('1st'); +sleep_without_cb_or_pred(1000); +deasync.loopUntilNoMoreEvents(); +console.log('3rd'); +t.ref(); // should make loopUntilNoEvents() to block +deasync.loopUntilNoMoreEvents(); + +// Expected order: ls -la, "async2", request setTimeout(function () { - console.log('async'); + console.log('async2'); }, 1000); - console.log(exec('ls -la')); sleep(2000); console.log(request('http://nodejs.org'));