Nodejs co 常见使用场景介绍

Nodejs co 常见使用场景介绍

co 常见使用场景

注意:目前 co 4.x 版本基于 Promise 实现,文章中的某些内容可能不适用,但思想是相同的

定时器 Timers

使用 co-defer

var defer = require('co-defer')

defer.setImmediate(function* () { console.log(‘setImmediate’); });

defer.nextTick(function* () { console.log(‘nextTick’); });

var timer1 = defer.setInterval(function* () { console.log(‘setTimeout 100ms’); clearTimeout(timer1); }, 100);

var timer2 = defer.setInterval(function* () { console.log(‘setInterval 100ms’); clearInterval(timer2); }, 100);

并发

数组形式

co(function* () {
  var rs = yield [
    get(1),
    get(2),
    get(3),
    get(4),
  ];
  console.log(rs);
  // [1, 2, 3, 4]
})();

键值对形式

co(function* () {
  var data = yield {
    name: getName(),
    age: getAge()
  };
  console.log(data);
  // { name: 'fengmk2', age: 18 }
})();

限制最大并发数

co 默认没有并发数限制, 可以通过 co-parallel 来限制并发数

var parallel = require('co-parallel');
var request = require('co-request');
var co = require('co');

var urls = [ ‘http://google.com’, ‘http://yahoo.com’, ‘http://ign.com’, ‘http://cloudup.com’, ‘http://myspace.com’, ‘http://facebook.com’, ‘http://segment.io’ ];

function* status(url) { console.log(‘GET %s’, url); return (yield request(url)).statusCode; }

co(function* () { var reqs = urls.map(status); var res = yield parallel(reqs, 2); console.log(res); })();

并发请求容错处理

co-gather 并发多个请求, 即使其中有一些请求错误了, 也能容错返回

var gather = require('co-gather');
var wait = require('co-wait');
var co = require('co');

var index = 0; function* random(val) { var i = index++; yield wait(Math.random() * 100); if (Math.random() > 0.5) { throw new Error(‘error’); } return {index: i, value: val}; }

co(function* () { var ret = yield gather([ random(1), random(2), random(3), random(4), random(5) ]); console.log(ret); })();

=>

[
  { isError: false, value: {index: 0, value: 1} },
  { isError: true, error: [Error: error] },
  { isError: true, error: [Error: error] },
  { isError: true, error: [Error: error] },
  { isError: false, value: {index: 4, value: 5} }
]

默认并发数为 concurrency = 5, 可以自行设置并发数 gather(thunks, [concurrency])

只取最快响应的

co-any 并发多个请求, 返回最快响应的一个结果

var any = require('co-any');
var wait = require('co-wait');
var co = require('co');

function* random(val) { yield wait(Math.random() * 100); if (Math.random() > 0.5) { throw new Error(‘error’); } return val; }

co(function* () { var ret = yield any([ random(1), random(2), random(3), random(4), random(5) ]); console.log(ret); })();

=>

{
  _key: 1,
  value: 2
}

事件 EventEmitter

事件监听者支持 GeneratorFunction

使用 co-event-wrap

var co = require('co');
var http = require('http');
var eventWrap = require('co-event-wrap');
var fs = require('co-fs');

co(function* () { var req = http.get(‘http://cnodejs.org’); eventWrap(req); req.on(‘response’, function* (res) { res = eventWrap(res); var datas = []; res.on(‘data’, function* (data) { datas.push(data); }); res.on(‘end’, function* () { var body = Buffer.concat(datas); yield fs.writeFile(__dirname + ‘/cnodejs.html’, body); console.log(‘got %d bytes, headers: %j’, body.length, res.headers); }); }); })();

通过 while 方式处理事件

co-event 帮你实现

var event = require('co-event');

var e; while (e = yield event(emitter)) { switch (e.type) { case ‘end’: break;

case 'close':
  break;

case 'error':
  break;

} }

emitter 原来的事件依旧会触发, 但是 error 事件不会被触发, 否则抛错无法被处理.

理解上面代码, 你必须以纯同步的思维来理解.

有爱


16 回复

Node.js co 常见使用场景介绍

定时器 Timers

co 模块可以与 co-defer 结合使用来处理异步定时器。以下是一个示例:

var defer = require('co-defer')

defer.setImmediate(function* () {
  console.log('setImmediate');
});

defer.nextTick(function* () {
  console.log('nextTick');
});

var timer1 = defer.setInterval(function* () {
  console.log('setInterval 100ms');
  clearInterval(timer1);
}, 100);

var timer2 = defer.setTimeout(function* () {
  console.log('setTimeout 100ms');
  clearTimeout(timer2);
}, 100);

这段代码展示了如何使用 co-defer 来处理 setImmediate, nextTick, setIntervalsetTimeout 的异步操作。

并发

数组形式

co(function* () {
  var rs = yield [
    get(1),
    get(2),
    get(3),
    get(4),
  ];
  console.log(rs);
  // [1, 2, 3, 4]
})();

上述代码中,get 函数可以是任何返回 Promise 的异步函数。co 会并行执行这些函数,并将结果收集到一个数组中。

键值对形式

co(function* () {
  var data = yield {
    name: getName(),
    age: getAge()
  };
  console.log(data);
  // { name: 'fengmk2', age: 18 }
})();

这段代码展示了如何并行执行多个异步操作,并将结果组织成对象的形式。

限制最大并发数

使用 co-parallel 可以限制并发数量:

var parallel = require('co-parallel');
var request = require('co-request');
var co = require('co');

var urls = [
  'http://google.com',
  'http://yahoo.com',
  'http://ign.com',
  'http://cloudup.com',
  'http://myspace.com',
  'http://facebook.com',
  'http://segment.io'
];

function* status(url) {
  console.log('GET %s', url);
  return (yield request(url)).statusCode;
}

co(function* () {
  var reqs = urls.map(status);
  var res = yield parallel(reqs, 2);
  console.log(res);
})();

这段代码限制了最多同时进行两个并发请求。

并发请求容错处理

使用 co-gather 可以处理并发请求的容错问题:

var gather = require('co-gather');
var wait = require('co-wait');
var co = require('co');

var index = 0;
function* random(val) {
  var i = index++;
  yield wait(Math.random() * 100);
  if (Math.random() > 0.5) {
    throw new Error('error');
  }
  return {index: i, value: val};
}

co(function* () {
  var ret = yield gather([
    random(1),
    random(2),
    random(3),
    random(4),
    random(5)
  ]);
  console.log(ret);
})();

输出结果类似于:

[
  { isError: false, value: {index: 0, value: 1} },
  { isError: true, error: [Error: error] },
  { isError: true, error: [Error: error] },
  { isError: true, error: [Error: error] },
  { isError: false, value: {index: 4, value: 5} }
]

co-gather 会捕获所有异常并返回一个包含结果和错误信息的对象数组。

只取最快响应的

使用 co-any 可以获取最快的响应结果:

var any = require('co-any');
var wait = require('co-wait');
var co = require('co');

function* random(val) {
  yield wait(Math.random() * 100);
  if (Math.random() > 0.5) {
    throw new Error('error');
  }
  return val;
}

co(function* () {
  var ret = yield any([
    random(1),
    random(2),
    random(3),
    random(4),
    random(5)
  ]);
  console.log(ret);
})();

输出结果类似于:

{
  _key: 1,
  value: 2
}

co-any 会返回最快完成的异步操作的结果。

事件 EventEmitter

事件监听者支持 GeneratorFunction

使用 co-event-wrap 可以处理事件监听:

var co = require('co');
var http = require('http');
var eventWrap = require('co-event-wrap');
var fs = require('co-fs');

co(function* () {
  var req = http.get('http://cnodejs.org');
  eventWrap(req);
  req.on('response', function* (res) {
    res = eventWrap(res);
    var datas = [];
    res.on('data', function* (data) {
      datas.push(data);
    });
    res.on('end', function* () {
      var body = Buffer.concat(datas);
      yield fs.writeFile(__dirname + '/cnodejs.html', body);
      console.log('got %d bytes, headers: %j', body.length, res.headers);
    });
  });
})();

通过 while 方式处理事件

使用 co-event 可以简化事件处理逻辑:

var event = require('co-event');

var e;
while (e = yield event(emitter)) {
  switch (e.type) {
    case 'end':
      break;

    case 'close':
      break;

    case 'error':
      break;
  }
}

这样可以方便地处理事件流,并且避免了直接处理错误事件导致的抛出异常问题。

希望本文对你有用 ^_^


更多与 co 控制流相关的东西可以在 cojs 里面找

应该弄一个koa 跟co得群 大家可以一起讨论

好东西

赞!

赞 && mark

苏大大高质量好文,学习中~,稳定版什么时候能支持这个特性啊~

koa 2.x 不再用 co 了。纪念下。

赞一个!

一、二级标题设置的差别再大一点就完美了!

Node.js co 常见使用场景介绍

co 是一个基于 Generator 函数的流程控制库,它可以让你更方便地处理异步操作。以下是一些常见的使用场景及示例代码。

定时器

你可以使用 co-defer 库来在 Generator 函数中使用定时器。

var defer = require('co-defer');

defer.setImmediate(function* () {
  console.log('setImmediate');
});

defer.nextTick(function* () {
  console.log('nextTick');
});

var timer1 = defer.setInterval(function* () {
  console.log('setInterval 100ms');
  clearInterval(timer1);
}, 100);

var timer2 = defer.setTimeout(function* () {
  console.log('setTimeout 100ms');
  clearTimeout(timer2);
}, 100);

并发

数组形式

可以并发执行多个函数,并将结果收集在一起。

co(function* () {
  var rs = yield [
    get(1),
    get(2),
    get(3),
    get(4),
  ];
  console.log(rs); // [1, 2, 3, 4]
})();
键值对形式

可以并发执行多个函数,并将结果以对象形式返回。

co(function* () {
  var data = yield {
    name: getName(),
    age: getAge()
  };
  console.log(data); // { name: 'fengmk2', age: 18 }
})();
限制最大并发数

可以使用 co-parallel 库来限制并发数量。

var parallel = require('co-parallel');
var request = require('co-request');
var co = require('co');

var urls = [
  'http://google.com',
  'http://yahoo.com',
  'http://ign.com',
  'http://cloudup.com',
  'http://myspace.com',
  'http://facebook.com',
  'http://segment.io'
];

function* status(url) {
  console.log('GET %s', url);
  return (yield request(url)).statusCode;
}

co(function* () {
  var reqs = urls.map(status);
  var res = yield parallel(reqs, 2);
  console.log(res);
})();

并发请求容错处理

可以使用 co-gather 库来并发多个请求,即使有些请求失败,也可以容错返回。

var gather = require('co-gather');
var wait = require('co-wait');
var co = require('co');

var index = 0;
function* random(val) {
  var i = index++;
  yield wait(Math.random() * 100);
  if (Math.random() > 0.5) {
    throw new Error('error');
  }
  return {index: i, value: val};
}

co(function* () {
  var ret = yield gather([
    random(1),
    random(2),
    random(3),
    random(4),
    random(5)
  ]);
  console.log(ret);
})();

只取最快响应的

可以使用 co-any 库来并发多个请求,返回最快响应的一个结果。

var any = require('co-any');
var wait = require('co-wait');
var co = require('co');

function* random(val) {
  yield wait(Math.random() * 100);
  if (Math.random() > 0.5) {
    throw new Error('error');
  }
  return val;
}

co(function* () {
  var ret = yield any([
    random(1),
    random(2),
    random(3),
    random(4),
    random(5)
  ]);
  console.log(ret);
})();

这些示例展示了如何使用 co 库来处理各种异步操作,提高代码的可读性和效率。

回到顶部