将承诺包装到同步function中

我正在编写一个节点CLI,其中同步行为通常比asynchronous更合适,我想能够利用以下约定:

# Write functional code as an async function which returns a Promise function foobar() { ... } # Uses async function but blocks on promise fulfillments function foobarSync() { ... } 

所以例如 – 使用RSVP承诺实现 – 我已经编写了以下用于调用shell脚本的asynchronous函数:

 var shell = function (params,options) { options = extend({timeout: 4000},options); var commandResponse = ''; var errorMessage =''; // resolve with a promise return new RSVP.Promise(function(resolve,reject) { var spawn = require('child_process').spawn; var timeout = setTimeout(function() { reject(new Error('Timed out')); // fulfil promise }, options.timeout); try { var shellCommand = spawn(params.shift(),params); } catch (err) { clearTimeout(timeout); reject(err); // fulfil promise } shellCommand.stdout.setEncoding('utf8'); shellCommand.stderr.setEncoding('utf8'); shellCommand.stdout.on('data', function (data) { commandResponse = commandResponse + data; }); shellCommand.stderr.on('data', function (data) { errorMessage = errorMessage + data; }); shellCommand.on('close', function (code) { if(code !== 0) { clearTimeout(timeout); reject({code:code, message:errorMessage}); // fulfil promise } else { clearTimeout(timeout); resolve(commandResponse); // fulfil promise } }); }); }; 

这工作,现在我想同步:

  # Works shell(['ls','-l']).then( function (results) { console.log('Result was: %s', results); }); # Would like to see work var results = shellSync(['ls','-l']); 

我认为会为shellSync工作的是:

 var shellSync = function (params,options) { options = extend({pollingInterval: 100},options); var shellResults = null; shell(params,options).then( function(results) { console.log('Results: %s', results); shellResults = results; // return results; }, function(err) { console.log('Error: %s', err); shellResults = err; // return err; } ); while(!shellResults) { // wait until a Promise is returned or broken (and sets the shellResults variable) } return shellResults; }; 

不幸的是,这只是运行,从不返回。 我虽然也许而不是while循环,我会实现轮询间隔来执行条件语句:

  var polling = setInterval(function() { // return once shellResults is set; // this setting takes place when either a resolve() or reject() // is called in Promise if(shellResults) { console.log('results are available'); clearInterval(polling); return shellResults; } },options.pollingInterval); while(1) { // wait } 

当然,删除while循环会导致函数立即返回(还有一个尚未实现的承诺)。 所以我试图把while循环的“等待”function与实现的轮询频率结合起来

最简单的方法是在内部代码上使用同步API,如果您希望它是同步的,但是您想要将asynchronous代码包装为同步,对不对?

我认为这可以通过使用纤维https://www.npmjs.org/package/fibers )来实现,或者更具体地说是期货 ,一个小例子

 var Future = require("fibers/future"); // async API, will be wrapped by syncFoo var asyncFoo = function(cb) { setTimeout(function() { cb("foo"); }, 1500); }; var syncFoo = function() { var future = new Future(); console.log("asyncFoo will be called"); asyncFoo(function(x) { future.return(x); }); console.log("asyncFoo ended"); return future.wait(); }; (function() { console.log("* Syncfoo will be called"); syncFoo(); console.log("* Syncfoo ended"); console.log("* Syncfoo will be called again"); syncFoo(); console.log("* Syncfoo ended again"); }).future()(); 

更具体的你的代码:

 var shellSync = function(params, options) { var future = new Future(); options = extend({pollingInterval: 100},options); var shellResults = null; shell(params,options).then( function(results) { console.log('Results: %s', results); future.return({results: results}); }, function(err) { console.log('Error: %s', err); future.return({err: err}); } ); var ret = future.wait(); if (ret.err) { throw ret.err; } else { return ret.results; } }; 

编辑注意 :你应该包装所有(function(){…})。 在光纤上运行