Skip to content

Instantly share code, notes, and snippets.

@stableShip
Last active July 5, 2016 07:37
Show Gist options
  • Save stableShip/b74a51d60e5ce2e674081bd6013161d5 to your computer and use it in GitHub Desktop.
Save stableShip/b74a51d60e5ce2e674081bd6013161d5 to your computer and use it in GitHub Desktop.
co流程控制
---
title: co流程控制
date: 2016-04-10 16:07:43
tags: [co,nodejs]
categories: [co,nodejs]
---
# co流程控制
## nodejs常见异步流程
#### 使用回调
```
fs.readFile("./file.js",function(err,data){
console.log(data.toString());
})
```
#### 使用promise
```
var Promise = require("bluebird")
var fs = require("fs");
fs = Promise.promisifyAll(fs);
fs.readFileAsync("./test.js").then(function(data){
console.log(data.toString());
})
```
#### 使用co+promise
```
var fs = require("fs");
var Promise = require("bluebird")
fs = Promise.promisifyAll(fs);
co(function* (){
var data = yield fs.readFileAsync('./test.js');
console.log(data.toString());
})
```
结论:使用co模块编写代码,形式与同步代码一致,没有回调和then,逻辑更加清晰。
-----
## co for循环
```
var fs = require("fs");
var Promise = require("bluebird")
fs = Promise.promisifyAll(fs);
co(function* (){
for(var i = 0; i < 2; i++){
var data = yield fs.readFileAsync('./test.js');
console.log(data.length, i);
}
})
```
和同步逻辑一致, 读取完文件后才会输出数据长度 与 i 的数值。
-----
## co while循环
```
var fs = require("fs");
var Promise = require("bluebird")
fs = Promise.promisifyAll(fs);
co(function* (){
var i = 0;
while(i < 10){
var data = yield fs.readFileAsync('./test.js');
console.log(data.length, i);
i++;
}
})
```
和同步逻辑一致, 读取完文件后才会输出数据长度 与 i 的数值。
-----
## co 并发
`并行执行多个函数,每个函数都是立即执行,不需要等待其它函数先执行。传给最终callback的数组中的数据按照tasks中声明的顺序,而不是执行完成的顺序。 `
```
var parallel = require('co-parallel');
var Promise = require("bluebird")
var co = require("co");
var fs = require("fs");
co(function* () {
// 创建多个promise
var promise = new Promise(function(resolve){
setTimeout(function(){
resolve(1);
},200)
})
var promises = [];
// 将所有promise保存到一个数组
for(var i=0;i<100000;i++){
promises.push(promise);
}
var start = new Date().getTime();
// yield 这个数组
// var res = yield promises
// bluebird 的promise自2.0之后不允许yield 数组(Promise.all也无法yield),相关链接https://github.com/petkaantonov/bluebird/pull/237
// 所以必须使用co-parallel 进行包装,并且能够控制并发数量,默认并发数:5
var res = yield parallel(promises)
console.log(res,res.legth,new Date().getTime()- start);
});
```
-----
## co 串联
` 有多个异步函数需要依次调用,一个完成之后才能执行下一个。各函数之间没有数据的交换,仅仅需要保证其执行顺序。这时可使用series`
```
// promise:
Promise.mapSeries([{timeout: 100, value: 1},
{timeout: 200, value: 2}], function (item) {
return Promise.delay(item.timeout, item.value);
}).then(function(results){
console.log(results) // [ 1, 2 ]
})
```
```
// co:
co(function* (){
var results = yield Promise.mapSeries([{timeout: 100, value: 1},
{timeout: 5000, value: 2}], co.wrap(function* (item) {
return Promise.delay(item.timeout, item.value);
}))
console.log(results);
}).catch((err)=>{
console.log(err);
})
```
`mapSeries 和 each 的区别: mapSeries返回处理函数处理后的结果,each返回传入参数`
`mapSeries 和 map 的区别: mapSeries等待上一个处理函数执行完毕再执行下一个,map直接执行`
[参考链接](http://bluebirdjs.com/docs/api/promise.mapseries.html)
------
## co错误处理
```
co(function* (){
try{
// 针对某个特殊的错误进行try,catch
try {
throw "test"
}catch (err){
console.log(err); //test
}
//可以继续执行
var results = yield Promise.mapSeries([{timeout: 500, value: 1},
{timeout: 5000, value: 2},{timeout: 100, value: 3}], co.wrap(function* (item) {
console.log(item)
return Promise.delay(item.timeout, item.value)
}))
console.log(results);
}catch(err){
console.log(err);
}
})
```
-----
## co编写函数与调用
```
// 函数
function test() {
return co(function* () {
try {
var results = yield Promise.resolve([1,2])
return results;
} catch (err) {
console.log(err);
}
})
}
// 调用
co(function* (){
var results = yield test();
console.log(results); //[1,2]
})
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment