Skip to content

Commit

Permalink
1. Support define generator method: `PromiseClass.create({*method(){ …
Browse files Browse the repository at this point in the history
…}});`

2. Promise callback can use generator function: `.then(function*(){ })`
  • Loading branch information
yaniswang committed Nov 9, 2015
1 parent 1bbe4d3 commit 056a38a
Show file tree
Hide file tree
Showing 7 changed files with 350 additions and 186 deletions.
7 changes: 7 additions & 0 deletions CHANGE.md
@@ -1,6 +1,13 @@
PromiseClass change log
====================

## ver 0.9.5 (2015-11-9)

add:

1. Support define generator method: `PromiseClass.create({*method(){ }});`
2. Promise callback can use generator function: `.then(function*(){ })`

## ver 0.9.4 (2015-11-8)

change:
Expand Down
42 changes: 34 additions & 8 deletions README.md
Expand Up @@ -22,6 +22,7 @@ Features
5. Support addMethod & addPropertie after class define
6. Support generator & ES7 await
7. Support async callback & promise & generator mix use
8. Supoort define generator method, and promise callback support generator function

Quick start
======================
Expand All @@ -38,39 +39,49 @@ Try it:
},

syncMethod(n){
console.log('syncMethod called');
console.log('syncMethod called : '+n);
return 'syncMethod return : '+n;
},

asyncMethod1(n, done){
console.log('asyncMethod1 called');
console.log('asyncMethod1 called : '+n);
this.asyncMethod2(n).then(function(){
console.log('asyncMethod1 done');
console.log('asyncMethod1 done : '+n);
done(null, 'asyncMethod1 return : '+n);
}).catch(done);
},

asyncMethod2(n, done){
console.log('asyncMethod2 called');
console.log('asyncMethod2 called : '+n);
setTimeout(function(){
console.log('asyncMethod2 done');
console.log('asyncMethod2 done : '+n);
done(null, 'asyncMethod2 return : '+n);
}, n);
},

*generatorMethod1(n){
console.log('generatorMethod1 called : '+n);
return yield this.asyncMethod2(n);
},

propertie1: 1,
propertie2: 2

});

// add async method
App.addMethod('asyncMethod3', function(n, done){
console.log('asyncMethod3 called');
console.log('asyncMethod3 called : '+n);
setTimeout(function(){
console.log('asyncMethod3 done');
console.log('asyncMethod3 done : '+n);
done(null, 'asyncMethod3 return : '+ n);
}, n);
});
// add generator method
App.addMethod('generatorMethod2', function*(n){
console.log('generatorMethod2 called : '+n);
return yield this.asyncMethod2(n);
});
// add propertie
App.addPropertie('propertie3', 3);

Expand All @@ -81,6 +92,7 @@ Try it:
var app = new App('async');
app.syncMethod(0, function(error, ret){
console.log(ret);
console.log('--------------------------');
app.asyncMethod1(1, function(error, ret){
console.log(ret);
console.log('================ async end ================');
Expand All @@ -98,10 +110,13 @@ Try it:
var app = new App('promise');
app.syncMethod(0).then(function(ret){
console.log(ret);
console.log('--------------------------');
}).asyncMethod1(1).then(function(ret){
console.log(ret);
console.log('--------------------------');
}).asyncMethod2(2).then(function(ret){
console.log(ret);
console.log('--------------------------');
}).asyncMethod3(3).then(function(ret){
console.log(ret);
console.log('================ promise end ================');
Expand All @@ -120,17 +135,27 @@ Try it:
yield app.syncMethod(0).then(function(ret){
console.log(ret);
});
console.log('--------------------------');
yield app.asyncMethod1(1).then(function(ret){
console.log(ret);
});
console.log('--------------------------');
yield app.asyncMethod2(2).then(function(ret){
console.log(ret);
});
console.log('--------------------------');
yield app.asyncMethod3(3).then(function(ret){
console.log(ret);
});
console.log('--------------------------');
yield app.generatorMethod1(4).then(function*(ret){
console.log(ret);
return yield this.asyncMethod1(5);
}).then(function(ret){
console.log(ret);
});
}).then(function(){
console.log('done:');
console.log('done!');
console.log('================ generator end ================');
console.log('');
deferred.resolve();
Expand All @@ -146,6 +171,7 @@ Try it:




License
================

Expand Down
38 changes: 31 additions & 7 deletions example/demo.js
Expand Up @@ -8,39 +8,49 @@ var App = PromiseClass.create({
},

syncMethod(n){
console.log('syncMethod called');
console.log('syncMethod called : '+n);
return 'syncMethod return : '+n;
},

asyncMethod1(n, done){
console.log('asyncMethod1 called');
console.log('asyncMethod1 called : '+n);
this.asyncMethod2(n).then(function(){
console.log('asyncMethod1 done');
console.log('asyncMethod1 done : '+n);
done(null, 'asyncMethod1 return : '+n);
}).catch(done);
},

asyncMethod2(n, done){
console.log('asyncMethod2 called');
console.log('asyncMethod2 called : '+n);
setTimeout(function(){
console.log('asyncMethod2 done');
console.log('asyncMethod2 done : '+n);
done(null, 'asyncMethod2 return : '+n);
}, n);
},

*generatorMethod1(n){
console.log('generatorMethod1 called : '+n);
return yield this.asyncMethod2(n);
},

propertie1: 1,
propertie2: 2

});

// add async method
App.addMethod('asyncMethod3', function(n, done){
console.log('asyncMethod3 called');
console.log('asyncMethod3 called : '+n);
setTimeout(function(){
console.log('asyncMethod3 done');
console.log('asyncMethod3 done : '+n);
done(null, 'asyncMethod3 return : '+ n);
}, n);
});
// add generator method
App.addMethod('generatorMethod2', function*(n){
console.log('generatorMethod2 called : '+n);
return yield this.asyncMethod2(n);
});
// add propertie
App.addPropertie('propertie3', 3);

Expand All @@ -51,6 +61,7 @@ function async(){
var app = new App('async');
app.syncMethod(0, function(error, ret){
console.log(ret);
console.log('--------------------------');
app.asyncMethod1(1, function(error, ret){
console.log(ret);
console.log('================ async end ================');
Expand All @@ -68,10 +79,13 @@ function promise(){
var app = new App('promise');
app.syncMethod(0).then(function(ret){
console.log(ret);
console.log('--------------------------');
}).asyncMethod1(1).then(function(ret){
console.log(ret);
console.log('--------------------------');
}).asyncMethod2(2).then(function(ret){
console.log(ret);
console.log('--------------------------');
}).asyncMethod3(3).then(function(ret){
console.log(ret);
console.log('================ promise end ================');
Expand All @@ -90,15 +104,25 @@ function generator(){
yield app.syncMethod(0).then(function(ret){
console.log(ret);
});
console.log('--------------------------');
yield app.asyncMethod1(1).then(function(ret){
console.log(ret);
});
console.log('--------------------------');
yield app.asyncMethod2(2).then(function(ret){
console.log(ret);
});
console.log('--------------------------');
yield app.asyncMethod3(3).then(function(ret){
console.log(ret);
});
console.log('--------------------------');
yield app.generatorMethod1(4).then(function*(ret){
console.log(ret);
return yield this.asyncMethod1(5);
}).then(function(ret){
console.log(ret);
});
}).then(function(){
console.log('done!');
console.log('================ generator end ================');
Expand Down
60 changes: 53 additions & 7 deletions lib/promiseclass.js
Expand Up @@ -3,6 +3,7 @@
* Copyright (c) 2015, Yanis Wang <yanis.wang@gmail.com>
* MIT Licensed
*/
const co = require('co');

const PromiseClass = {
create: function(classDefines){
Expand All @@ -22,9 +23,22 @@ const PromiseClass = {
// hook Promise then function
let PromisePrototype = ChainPromise.prototype;
let rawThen = PromisePrototype.then;
PromisePrototype.then = function(){
PromisePrototype.then = function(onResolve, onReject){
let self = this;
let promise = rawThen.apply(self, arguments);
if(isGeneratorFunction(onResolve)){
// support then generator
let rawOnResolve = onResolve;
onResolve = function(){
return co(rawOnResolve.apply(self, arguments));
};
}
if(isGeneratorFunction(onReject)){
let rawOnReject = onReject;
onReject = function(){
return co(rawOnReject.apply(self, arguments));
};
}
let promise = rawThen.call(self, onResolve, onReject);
promise._context = self._context;
return promise;
};
Expand All @@ -42,8 +56,17 @@ const PromiseClass = {
callback = args.pop();
}
function done(error, ret){
callback && callback(error, ret);
error ? deferred.reject(error) : deferred.resolve(ret);
if(callback){
let newRet = callback.call(self, error, ret);
if(isGenerator(newRet)){
// support callback generator
newRet = co(newRet);
}
deferred.resolve(newRet);
}
else{
error ? deferred.reject(error) : deferred.resolve(ret);
}
}
// async modem hook done
if(isAsync){
Expand All @@ -53,7 +76,15 @@ const PromiseClass = {
let ret = fn.apply(self, args);
// sync mode
if(isAsync === false){
done(null, ret);
if(ret !== undefined && isGenerator(ret)){
// support method generator
co(ret).then(function(ret){
done(null, ret);
}).catch(done);
}
else{
done(null, ret);
}
}
}
catch(error){
Expand Down Expand Up @@ -98,11 +129,26 @@ const PromiseClass = {
function isCallback(arg){
if(typeof arg === 'function'){
var str = String(arg);
if(/^function(\s+(done|callback|cb))\s*\(/.test(str) ||
/^function(\s+\w+)?\s*\(\s*(error|err|e)\s*(,|\))/i.test(str)){
if(/^function\*?(\s+(done|callback|cb))\s*\(/.test(str) ||
/^function\*?(\s+\w+)?\s*\(\s*(error|err|e)\s*(,|\))/i.test(str)){
return true;
}
}
return false;
}

// check is generator function
function isGeneratorFunction(obj) {
var constructor = obj && obj.constructor;
if (constructor && ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName)) {
return true;
}
return false;
}

// check is generator
function isGenerator(obj) {
return obj && 'function' == typeof obj.next && 'function' == typeof obj.throw;
}

module.exports = PromiseClass;
10 changes: 6 additions & 4 deletions package.json
@@ -1,11 +1,12 @@
{
"name": "promiseclass",
"version": "0.9.4",
"version": "0.9.5",
"description": "Create Promise chain Class",
"main": "./index",
"dependencies": {},
"dependencies": {
"co": "4.6.0"
},
"devDependencies": {
"co": "4.6.0",
"expect.js": "0.3.1",
"grunt": "0.4.1",
"grunt-cli": "0.1.6",
Expand All @@ -15,7 +16,8 @@
"grunt-exec": "0.4.0",
"istanbul": "0.3.22",
"istanbul-coveralls": "1.0.3",
"mocha": "2.3.3"
"mocha": "2.3.3",
"mocha-generators": "1.2.0"
},
"scripts": {
"test": "mocha"
Expand Down

0 comments on commit 056a38a

Please sign in to comment.