co
Advanced tools
Comparing version 1.4.1 to 1.5.0
var Emitter = require('events').EventEmitter; | ||
var http = require('http'); | ||
var co = require('..'); | ||
var url = process.argv[2] || 'http://nodejs.org'; | ||
co(function *(){ | ||
var res = yield get('http://google.com'); | ||
console.log('-> %s', res.status); | ||
var res = yield get(url); | ||
console.log('-> %s', res.statusCode); | ||
var buf; | ||
while (buf = yield res.read()) { | ||
console.log(buf.toString()); | ||
var total = 0; | ||
while (buf = yield read(res)) { | ||
total += buf.length; | ||
console.log('\nread %d bytes (%d total):\n%j', buf.length, total, buf.toString()); | ||
} | ||
console.log('done'); | ||
}) | ||
}); | ||
// I couldn't get streams2 to work... so, here's a fake request :) | ||
function get(url) { | ||
console.log('GET %s', url); | ||
return function(done){ | ||
done(null, new Response); | ||
} | ||
var req = http.get(url); | ||
req.once('response', function(res) { | ||
done(null, res); | ||
}); | ||
req.once('error', function(err) { | ||
done(err); | ||
}); | ||
}; | ||
} | ||
function Response() { | ||
var self = this; | ||
this.status = 200; | ||
function read(res) { | ||
return function(done){ | ||
var id = setInterval(function(){ | ||
self.emit('data', new Buffer('hello')); | ||
}, 10); | ||
function onreadable() { | ||
// got a "readable" event, try to read a Buffer | ||
cleanup(); | ||
check(); | ||
} | ||
setTimeout(function(){ | ||
clearInterval(id); | ||
self.emit('end'); | ||
}, 200); | ||
} | ||
function onend() { | ||
// got an "end" event, send `null` as the value to signify "EOS" | ||
cleanup(); | ||
done(null, null); | ||
} | ||
Response.prototype.__proto__ = Emitter.prototype; | ||
function onerror(err) { | ||
// got an "error" event while reading, pass it upstream... | ||
cleanup(); | ||
done(err); | ||
} | ||
Response.prototype.read = function(){ | ||
var self = this; | ||
return function(done){ | ||
// push kinda sucks for this... we need to | ||
// handle whichever comes first with this hack | ||
self.once('data', function(buf){ | ||
self.removeListener('end', done); | ||
done(null, buf); | ||
}); | ||
function cleanup() { | ||
res.removeListener('readable', onreadable); | ||
res.removeListener('end', onend); | ||
res.removeListener('error', onerror); | ||
} | ||
self.on('end', done); | ||
} | ||
}; | ||
function check() { | ||
var buf = res.read(); | ||
if (buf) { | ||
// got a Buffer, send it! | ||
done(null, buf); | ||
} else { | ||
// otherwise, wait for any of a "readable", "end", or "error" event... | ||
// wow, streams2 kinda sucks, doesn't it? | ||
res.on('readable', onreadable); | ||
res.on('end', onend); | ||
res.on('error', onerror); | ||
} | ||
} | ||
// kick things off... | ||
check(); | ||
}; | ||
} |
0.5.0 / 2013-08-10 | ||
================== | ||
* add receiver propagation support | ||
* examples: update streams.js example to use `http.get()` and streams2 API | ||
1.4.1 / 2013-07-01 | ||
@@ -3,0 +9,0 @@ ================== |
21
index.js
@@ -22,5 +22,6 @@ | ||
function co(fn) { | ||
function co(fn, ctx) { | ||
var args = [].slice.call(arguments, 1); | ||
var gen = isGenerator(fn) ? fn : fn.apply(this, args); | ||
ctx = ctx || this; | ||
var done; | ||
@@ -63,3 +64,3 @@ | ||
// normalize | ||
ret.value = toThunk(ret.value); | ||
ret.value = toThunk(ret.value, ctx); | ||
@@ -69,3 +70,3 @@ // run | ||
try { | ||
ret.value(next); | ||
ret.value.call(ctx, next); | ||
} catch (e) { | ||
@@ -118,2 +119,3 @@ setImmediate(function(){ | ||
if (!Array.isArray(fns)) fns = [].slice.call(arguments); | ||
var ctx = this; | ||
@@ -139,5 +141,5 @@ return function(done){ | ||
try { | ||
fn = toThunk(fn); | ||
fn = toThunk(fn, ctx); | ||
fn(function(err, res){ | ||
fn.call(ctx, function(err, res){ | ||
if (finished) return; | ||
@@ -165,2 +167,3 @@ | ||
* @param {Mixed} obj | ||
* @param {Mixed} ctx | ||
* @return {Function} | ||
@@ -170,6 +173,6 @@ * @api private | ||
function toThunk(obj) { | ||
if (Array.isArray(obj)) obj = exports.join(obj); | ||
if (isGeneratorFunction(obj)) obj = obj(); | ||
if (isGenerator(obj)) obj = co(obj); | ||
function toThunk(obj, ctx) { | ||
if (Array.isArray(obj)) obj = exports.join.call(ctx, obj); | ||
if (isGeneratorFunction(obj)) obj = obj.call(ctx); | ||
if (isGenerator(obj)) obj = co(obj, ctx); | ||
if (isPromise(obj)) obj = promiseToThunk(obj); | ||
@@ -176,0 +179,0 @@ return obj; |
{ | ||
"name": "co", | ||
"version": "1.4.1", | ||
"version": "1.5.0", | ||
"description": "generator async flow control goodness", | ||
"keywords": ["async", "flow", "generator", "coro", "coroutine"], | ||
"keywords": [ | ||
"async", | ||
"flow", | ||
"generator", | ||
"coro", | ||
"coroutine" | ||
], | ||
"devDependencies": { | ||
"should": "~1.2.2", | ||
"mocha": "~1.10.0", | ||
"q": "~0.9.4" | ||
"q": "~0.9.4", | ||
"bench": "~0.3.5" | ||
}, | ||
"license": "MIT" | ||
} |
@@ -26,2 +26,5 @@ # Co | ||
- [co-exec](https://github.com/visionmedia/co-exec) - core `exec` function wrapper | ||
- [co-prompt](https://github.com/visionmedia/co-prompt) - terminal user input utilities | ||
- [co-express](https://github.com/mciparelli/co-express) - [express](https://github.com/visionmedia/express) wrapper that enables generators to be used as middlewares | ||
- [level-co](https://github.com/juliangruber/level-co) - levelup wrapper | ||
@@ -97,2 +100,20 @@ ## Example | ||
## Receiver propagation | ||
When `co` is invoked with a receiver it will propagate to most yieldables, | ||
allowing you to alter `this`. | ||
```js | ||
var ctx = {}; | ||
function foo() { | ||
assert(this == ctx); | ||
} | ||
co.call(ctx, function *(){ | ||
assert(this == ctx); | ||
yield foo; | ||
}); | ||
``` | ||
## API | ||
@@ -99,0 +120,0 @@ |
Sorry, the diff of this file is not supported yet
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
33939
24
994
349
4
9
1