发布一个异步控制流的Nodejs模块xchain

发布于 1周前 作者 yibo5220 来自 nodejs/Nestjs

发布一个异步控制流的Nodejs模块xchain

[xchain]是用于简化异步控制流的库,已经在npm上注册了。至于有什么用,用过[Step]的人会明白,但因为我觉得[Step]的异常处理方式是存在一定问题的。这个库的接口设计经过了很久的思考,应该是很简单且实用的。

用代码简要地说明:

var xchain = require('xchain');
var util = require('util');

xchain( // 在这个圆括号内的作为xchain的参数的两个函数 // 是并行执行的。 function(next) { setTimeout(function(){ next.foo = 1; util.log(‘next.foo completed’); next(); // 表示这个异步操作完成 }, 1000); // 模拟一个用时1秒的异步操作 }, function(next) { setTimeout(function() { next.bar = 2; util.log(‘next.bar completed’); next(); }, 2000); // 模拟一个用时2秒的异步操作 } )( // xchain()返回的也是一个函数,用法和上面相同, // 用链式的表达式来表示依赖关系 function(next) { util.log(‘foo=’, next.foo); util.log(‘bar=’, next.bar); throw { error : 1 }; // 抛出的异常会被传给run方法的回调捕获 }, function(next) { next(); } )( function(next) { throw { error : 2 }; } )( function(next) { // 不会执行到此处,自行揣摩传给run方法的回调 } ).run(function(err, next) { if (err.error == 1) next(); // 模拟一个可以恢复的错误 // 其他错误不处理 });

###简单的总结

  • 通过链式表达式的形式描述异步操作的依赖关系和并行关系,应该是比较简洁而清晰的。
  • 异步操作完成时将next当作函数来调用,以通知xchain当前异步操作完成,当所有并行的操作完成是,xchain会执行下一个(批)异步操作。
  • 为了方便数据的通信,也可以将next当作普通的对象使用(如有必要,也可以使用闭包)。
  • 在构建好异步控制流之后,调用run()方法开始从上而下执行。可以给run()方法传递一个异常处理函数,可以在异常处理函数中恢复控制流,或者中断控制流的执行(如不提供异常处理函数,一旦发生异常,默认按照依赖关系停止异步控制流的执行)。

此外,欢迎fork,comment和patch。 [xchain]: http://github.com/thynson/xchain [Step]: http://github.com/creationix/step


18 回复

发布一个异步控制流的Node.js模块xchain

今天,我发布了一个新的Node.js模块——xchain,它旨在简化异步控制流的管理。该模块已经在npm上注册,并且已经在一些项目中得到了应用。

用途

如果你之前使用过Step库,你可能会对xchain有所了解。虽然Step非常强大,但我发现它的异常处理机制存在一些问题。因此,我设计了xchain,希望它能够更加简单且实用。

示例代码

下面是一个简单的例子,展示了如何使用xchain来管理异步操作:

var xchain = require('xchain');
var util = require('util');

xchain(
  // 在这个圆括号内的两个函数是并行执行的
  function(next) {
    setTimeout(function(){
      next.foo = 1;
      util.log('next.foo completed');
      next(); // 表示这个异步操作完成
    }, 1000); // 模拟一个用时1秒的异步操作
  },
  function(next) {
    setTimeout(function() {
      next.bar = 2;
      util.log('next.bar completed');
      next();
    }, 2000); // 模拟一个用时2秒的异步操作
  }
)(
  // xchain()返回的也是一个函数,用法和上面相同,
  // 用链式的表达式来表示依赖关系
  function(next) {
    util.log('foo=', next.foo);
    util.log('bar=', next.bar);
    throw { error: 1 }; // 抛出的异常会被传给run方法的回调捕获
  },
  function(next) {
    next();
  }
)(
  function(next) {
    throw { error: 2 };
  }
)(
  function(next) {
    // 不会执行到此处,自行揣摩传给run方法的回调
  }
).run(function(err, next) {
  if (err && err.error === 1) {
    next(); // 模拟一个可以恢复的错误
  }
  // 其他错误不处理
});

简单总结

  1. 链式表达式:通过链式表达式的形式描述异步操作的依赖关系和并行关系,使得代码结构更加简洁和清晰。

  2. 异步操作完成通知:异步操作完成时,将next当作函数来调用,以通知xchain当前异步操作已完成。当所有并行的操作完成后,xchain会执行下一个(批)异步操作。

  3. 数据通信:为了方便数据的通信,也可以将next当作普通的对象使用(如有必要,也可以使用闭包)。

  4. 运行控制流:在构建好异步控制流之后,调用run()方法开始从上而下执行。可以给run()方法传递一个异常处理函数,在异常处理函数中恢复控制流或中断控制流的执行。如果不提供异常处理函数,一旦发生异常,默认按照依赖关系停止异步控制流的执行。

总结

xchain旨在简化异步控制流的管理,提供了一种更简洁、更灵活的方式来处理复杂的异步操作。欢迎大家试用、评论和贡献代码!


能简单介绍下你这个模块的工作流程吗?

感觉很高深,我想知道这个和老赵的wind.js还有eventproxy是什么关系呢?

这个不合适吧!用setTimeout来模拟执行时间不大可取! 毕竟执行一段代码你不知道是1秒还是2秒还是0.2秒、甚至20ms! 当然这是解决异步的一种方法,但是个人觉得不怎么靠谱!

汗,这是作者的示例,不是实现机制~ settimeout只是用来模拟一个异步操作

我不喜欢老赵的wind.js那样的,用编译的方式来达到异步,在js中,就应该尽量用异步的思想去思考问题。而eventproxy的接口太繁琐,完全可以用链式表达式将各个异步操作的依赖关系表示清楚。

github上的源代码吧,应该不是很难理解。

还没去看他的代码,但我感觉应该是使用递归实现的

var Step = require('step');
var con = require('console');

Step(
    function() {
        var next1 = this.parallel();
        var next2 = this.parallel();
        setTimeout(function() {
            next1({ error : 1}, 5);
        }, 100);
        setTimeout(function() {
            next2({ error : 2}, 20);
        }, 200);
    },
    function(err, a, b) {
        con.log(err);
        con.log(a);
        con.log(b);
    }
)

第一个异常{error : 1 }会被覆盖掉.

var xchain = require('xchain');
var con = require('console');

xchain(
  function(next) {
    setTimeout(function() {
      next({error : 1}); //异步调用中异常,不能用throw
    }, 100);
  }, 
  function(next) {
    next({error : 2});// 等价于 throw {error : 2};
  },
  function(next) {
    throw {error : 3};//等价于 next({error : 3});
  }
)(
  function(next) {
    
  }
).run(function(err, next) {
  con.log(err);
  next();
});

传给run方法的回调针对不同的异常会被调用三次

nodejs的技术欢迎加群聊262658247

想了解一下你的库和async库中的waterfall有什么差异?

想知道这样的代码用xchain有什么优势, 如果这个例子不能说明问题,能不能举个体现xchain优势的例子, 老赵看到了也说说wind的?

arr = [1,2,3,4,5,6,7,8,9];

async.reduce(arr, 0, function(result, item, cb){ cb(item > 5 ? 'stopped on '+item : null , result + item); }, function(err, result){ console.log(‘reduce’, err, result); });

async.waterfall([ function(cb){ cb(null, arr.map(function(item){ return item + 1; })) }, function(result, cb){ if(result[0] != 2) cb(null, result.map(function(item){ return item + 1; })) else cb(‘stopped on step 2’, result); }, function(result, cb){ cb(null, result.map(function(item){ return item + 1; })) } ], function(err, result){ console.log(‘waterfall’, err, result); })

另外给回帖功能提几个建议:

  • 提交了以后自己干嘛不能修改?
  • 能@某人就好了,和微博一样,github上的回复好像也有这种功能,就是引起某人注意

async.reduce和这个不是一个东西。 async.waterfall是完全串行的,目的也和xchain不一样,只有async.auto才有可比性。

没懂reduce要干嘛的……waterfall不就是串行嘛,用Wind.js写就是:

var r1 = arr.map(function(item) { return item + 1; }));
if (r1[0] == 2) throw 'stopped on step 2';

var r2 = r1.map(function(item) { return item + 1; }); var r3 = r2.map(function(item) { return item + 1; });

return r3;

不过你异步的点在哪里?

api确实比eventproxy要好。。

以下是关于发布 xchain Node.js 模块的内容:

xchain 是一个用于简化异步控制流的库,已在 npm 上注册。该库针对 Step 库的异常处理方式进行了改进,并经过长时间的思考设计,使得接口更加简单和实用。

以下是 xchain 的基本使用示例:

var xchain = require('xchain');
var util = require('util');

xchain(
  // 这两个函数并行执行
  function(next) {
    setTimeout(function(){
      next.foo = 1;
      util.log('next.foo completed');
      next(); // 表示当前操作完成
    }, 1000);
  },
  function(next) {
    setTimeout(function() {
      next.bar = 2;
      util.log('next.bar completed');
      next();
    }, 2000);
  }
)(
  // 依次执行后续的异步操作
  function(next) {
    util.log('foo=', this.foo);
    util.log('bar=', this.bar);
    throw { error: 1 };
  },
  function(next) {
    next();
  }
)(
  function(next) {
    throw { error: 2 };
  }
)(
  function(next) {
    // 不会执行到这里
  }
).run(function(err, next) {
  if (err && err.error == 1) {
    next(); // 恢复错误
  }
  // 其他错误默认停止执行
});

简单总结:

  • 使用链式表达式描述异步操作的依赖关系和并行关系,使代码简洁清晰。
  • 异步操作完成时调用 next() 函数通知 xchain 当前操作完成。
  • 可以将 next 对象当作普通对象使用,以便于数据传递。
  • 调用 run() 方法开始执行整个异步控制流,可传递异常处理函数来恢复或中断控制流。
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!