1. Generator函数
协程实现:yield暂停,next启动 数据交换和错误处理:yield和next参数,Generator内捕获外部错误 异步任务封装
var fetch = require ( 'node-fetch' )
function * g ( ) {
let res = yield fetch ( 'https://api.github.com/users/github' )
console. log ( res)
}
var t = g ( )
var res = t. next ( )
res. value
. then ( data => data. json ( ) )
. then ( data => t. next ( data) )
2. Thunk函数
参数求值策略:传值调用、传名调用 thunk函数的含义:使用临时函数实现传名调用
function Thunk ( fn) {
return function ( ... args) {
console. log ( this === global)
return function ( callback) {
return fn. call ( this , ... args, callback)
}
}
}
function f ( a, b) {
b ( a)
console. log ( this == obj)
}
var ft = Thunk ( f)
var obj = {
fun: ft ( 1 )
}
obj. fun ( console. warn)
var thunkify = require ( 'thunkify' )
var fs = require ( 'fs' )
thunkify ( fs. readFile) ( '1.txt' , 'utf-8' ) ( ( err, str) => {
console. log ( str)
} )
function thunkify ( fn) {
return function ( ) {
var args = new Array ( arguments. length) ;
var ctx = this ;
for ( var i = 0 ; i < args. length; ++ i) {
args[ i] = arguments[ i] ;
}
return function ( done) {
var called;
args. push ( function ( ) {
if ( called) return ;
called = true ;
done. apply ( null , arguments) ;
} ) ;
try {
fn. apply ( ctx, args) ;
} catch ( err ) {
done ( err) ;
}
}
}
} ;
function f ( ... arr) {
let callback = arr. pop ( )
let max = Math. max ( ... arr)
callback ( max)
callback ( max)
callback ( max)
}
var ft = thunkify ( f)
ft ( 1 , 3 , 5 , 7 , 11 ) ( console. log)
var fs = require ( 'fs' )
var thunkify = require ( 'thunkify' )
var readFileThunk = thunkify ( fs. readFile)
var g = function * ( ) {
console. log ( 1 , yield readFileThunk ( '1.txt' , 'utf-8' ) )
console. log ( 2 , yield readFileThunk ( '2.txt' , 'utf-8' ) )
}
var t = g ( )
t. next ( ) . value ( ( err, data) => {
t. next ( data) . value ( ( err, data) => {
t. next ( data)
} )
} )
var g = function * ( ) {
console. log ( 1 , yield readFileThunk ( '1.txt' , 'utf-8' ) )
console. log ( 2 , yield readFileThunk ( '2.txt' , 'utf-8' ) )
console. log ( 3 , yield readFileThunk ( '3.txt' , 'utf-8' ) )
console. log ( 4 , yield readFileThunk ( '4.txt' , 'utf-8' ) )
}
function run ( g) {
var t = g ( )
next ( )
function next ( err, data) {
let res = t. next ( data)
if ( ! res. done) {
res. value ( next)
}
}
}
run ( g)
3. co 模块
作用:用于Generator函数的自动执行 原理:封装了两种自动执行器(Thunk函数和Promise对象)
使用条件:yield后面只能是Thunk或Promise
var g = function * ( ) {
console. log ( 'co' , yield readFileThunk ( '1.txt' , 'utf-8' ) )
console. log ( 'co' , yield readFileThunk ( '2.txt' , 'utf-8' ) )
console. log ( 'co' , yield readFileThunk ( '3.txt' , 'utf-8' ) )
console. log ( 'co' , yield readFileThunk ( '4.txt' , 'utf-8' ) )
}
var co = require ( 'co' )
co ( g) . then ( ( ) => console. log ( 'over' ) )
var fs = require ( 'fs' )
function readFile1 ( fileName) {
return new Promise ( resolve => {
fs. readFile ( fileName, ( err, data) => {
resolve ( data)
} )
} )
}
function * g1 ( ) {
let r1 = yield readFile1 ( '1.txt' )
let r2 = yield readFile1 ( '2.txt' )
console. log ( r1. toString ( ) , r2. toString ( ) )
}
var t1 = g1 ( )
t1. next ( ) . value. then ( data => {
t1. next ( data) . value. then ( data => {
t1. next ( data)
} )
} )
function run1 ( g) {
let t = g ( )
next ( )
function next ( data) {
let res = t. next ( data)
if ( res. done) {
return res. value
} else {
res. value. then ( data => {
next ( data)
} )
}
}
}
run1 ( g1)
var co = require ( 'co' )
co ( function * ( ) {
return yield [
Promise. resolve ( 1 ) ,
Promise. resolve ( 2 )
]
} ) . then ( data => console. log ( data) )
var co = require ( 'co' )
var fs = require ( 'fs' )
var stream = fs. createReadStream ( 'Generator应用1.js' )
var count = 0
co ( function * ( ) {
while ( true ) {
const res = yield Promise. race ( [
new Promise ( resolve => stream. once ( 'data' , resolve) ) ,
new Promise ( resolve => stream. once ( 'end' , resolve) ) ,
new Promise ( ( res, rej) => stream. once ( 'error' , rej) ) ,
] )
if ( ! res) {
break
}
stream. removeAllListeners ( 'data' ) ;
stream. removeAllListeners ( 'end' ) ;
stream. removeAllListeners ( 'error' ) ;
count += ( res. toString ( ) . match ( /yield/g ) || [ ] ) . length;
}
console. log ( count)
} )