我正在编写一个基于Node的CLI,其中同步行为通常比异步更合适,我希望能够利用以下约定:
# 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脚本:
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循环的“等待”功能与轮询频率结合起来实现。
js
本身不支持多线程。只要你在while(!shellResults) {}
块中,没有其他的js
代码会被执行。 - t.niese