按顺序调用JavaScript代码的另一种方法是在两者之间拖延
我有这个代码最初在Python中。
SendSerialPortCommand("XXX") time.delay(0.5) SendSerialPortCommand("YYY")
我把这个代码转换为node.js,但代码看起来更丑。
SendSerialPortCommand("XXX"); setTimeout(function () { SendSerialPortCommand("YYY"); }, 500);
想象一下,如果我的Python代码看起来像这样。
SendSerialPortCommand("XXX") time.delay(0.5) SendSerialPortCommand("YYY") time.delay(0.5) SendSerialPortCommand("AAA") time.delay(0.5) SendSerialPortCommand("BBB")
使用setTimeout()
内的setTimeout()
,node.js代码看上去真的很难看。
怎样才能改善node.js代码的可读性? 我不在乎这个问题违反JavaScript的asynchronous性质。 重要的是可读性。
1.单线解决scheme:
以前接受的解决scheme只是使事情复杂化,并没有带来任何可读性或改进。 像这样做,只有一行 :
setTimeout(function(){ SendSerialPortCommand("XXX"); }, 500); setTimeout(function(){ SendSerialPortCommand("YYY"); }, 1500); setTimeout(function(){ SendSerialPortCommand("ZZZ"); }, 2000);
2.简单的可configuration解决scheme:
如果要使其可configuration ,请将选项移至上面的configuration,然后在循环中调用 :
var schedulerData = [ {delay: 500, params: "XXX"}, {delay: 1500, params: "YYY"}, {delay: 2000, params: "ZZZ"} ]; for (var i in schedulerData) { var doTimeout = function(param, delay) { setTimeout(function(){ SendSerialPortCommand(param); }, delay ); }; doTimeout(schedulerData[i].params, schedulerData[i].delay); }
这里是JSFiddle ,玩。
3.使用节点模块node-fibers
如果您想要通过node.js的高级解决scheme来“炫耀”,您可以采取node-fibers
方式,并创build睡眠function,就像手册一样。
var Fiber = require('fibers'); function sleep(ms) { var fiber = Fiber.current; setTimeout(function() { fiber.run(); }, ms); Fiber.yield(); } Fiber(function() { SendSerialPortCommand("XXX"); sleep(1000); SendSerialPortCommand("YYY"); }).run(); console.log('still executing the main thread');
node-fibers
实现正在其他许多小型库中使用,就像WaitFor一样。 更多信息可以在这里find。
4.使用Promise
& Deferred
对象
您可以创build基于Promise的超时function。 乔描述了一个可能的实现。 但是我会提供一些小代码片断,以便更好地理解它是如何工作的,使用jQuery中的Defferred
:
function wait(ms) { var deferred = $.Deferred(); setTimeout(deferred.resolve, ms); // We just need to return the promise not the whole deferred. return deferred.promise(); } // Use it wait(500).then(function () { SendSerialPortCommand("XXX"); }).wait(500).then(function () { SendSerialPortCommand("YYY"); });
如果不支持promise,则需要获取ECMAScript的polyfills ,例如core-js
包中的Promises或Promises / A +实现的其他独立组件。
所得到的,也可以作为NPM的Deffered
包得到,这个概念在这里很好的描述 。
你可以使用promise:
function Delay(duration) { return new Promise((resolve) => { setTimeout(() => resolve(), duration); }); } function SendSerialPortCommand(command) { // Code that actually sends the command goes here... console.log(command); return Promise.resolve(); } Promise.resolve() .then(() => SendSerialPortCommand("XXX")) .then(() => Delay(500)) .then(() => SendSerialPortCommand("YYY")) .then(() => Delay(500)) .then(() => SendSerialPortCommand("AAA")) .then(() => Delay(500)) .then(() => SendSerialPortCommand("BBB"));
或者,包括延迟到SendSerialPortCommand中:
function SendSerialPortCommand(command, duration) { return new Promise((resolve) => { setTimeout(() => { // Code that actually sends the command goes here... resolve(); }, duration); }); } Promise.resolve() .then(() => SendSerialPortCommand("XXX", 500)) .then(() => SendSerialPortCommand("YYY", 500)) .then(() => SendSerialPortCommand("AAA", 500)) .then(() => SendSerialPortCommand("BBB", 500));
节点4+是使用箭头function所必需的,但如果需要的话,可以在没有它们的情况下轻松完成。
注意稍后执行function的时间。
var scheduler = (function(){ var timer; function exec(call, delay){ //clearTimeout(timer); timer = setTimeout(call, delay); }; return exec; })() SendSerialPortCommand("XXX"); scheduler(function(){SendSerialPortCommand("YYY")}, 500); scheduler(function(){SendSerialPortCommand("AAA")}, 1000); scheduler(function(){SendSerialPortCommand("BBB")}, 1500);
既然你问了其他的方法,我也会写一个。
var commandIterator = 0; var portCommands = [ 'YYY', 'AAA' ]; SendSerialPortCommand(portCommands[commandIterator++]) var yourInterval = setInterval(function(){ SendSerialPortCommand(portCommands[commandIterator++]) }, 500);
在任何时候你需要停止执行那些你只需要调用clearInterval(yourInterval)
如果你仍然关心可读性,你可以把迭代器放在setInterval中,并把内容包装在一个漂亮的函数中。 祝你好运!
- Object.create(Function.prototype)=>创buildinheritance属性的函数
- 预期testing不适用于ES6 / ES2015 Set对象
- 如何在数组中search多个可能的匹配
- 节点 – 如何访问POST路由中间件中的请求
- 使用moment.js修改date
- 使用restangular将表单数据从AngularJs前端发布到NodeJS RESTful API
- 将对象数组转换为与nodejs / pg / unnest兼容的数组
- 我的asynchronous包装meteor包的问题
- 如何区分经过身份validation的用户在客户端与Passport和node.js?