node.js - Proper way to make callbacks async by wrapping them using `co`? -
it 2016, node has had full es6 support since v4, , promises have been around since 0.12. it's time leave callbacks in dust imo.
i'm working on commander.js-based cli util leverages lot of async operations - http requests , user input. want wrap commander action
s in async functions can treated promises, , support generators (useful co-prompt
library i'm using user input).
i've tried wrapping cb co
in 2 ways:
1) program.command('mycmd') .action(program => co(function* (program) {...}) .catch(err => console.log(err.stack)) );
and
2) program.command('mycmd').action(co.wrap(function* (program) { .. }));
the problem 1) program
parameter isn't passed
the problem 2) errors swallowed...
i'd working yields nicer code in use case - involving lot of http requests , waiting user input using co-prompt
library..
is better option altogether perhaps wrap program.command.prototype.action
somehow?
thanks!
i've used bespoke version of co
db.exec
function uses yield database request. can pass parameters generator function (i pass in connection object - see comment it).
here db.exec function similar co
does
exec(generator) { var self = this; var it; debug('in db.exec iterator'); return new promise((accept,reject) => { debug('in db.exec promise'); var myconnection; var onresult = lastpromiseresult => { debug('in db.exec onresult'); var obj = it.next(lastpromiseresult); if (!obj.done) { debug('db.exec iterator not done yet'); obj.value.then(onresult,reject); } else { if (myconnection) { myconnection.release(); debug('db.exec released connection'); } accept(obj.value); debug('db.exec promise resolved value %d',obj.value); } }; self._connection().then(connection => { debug('db.exec got connection'); myconnection = connection; = generator(connection); //this passes generator onresult(); //starts generator }).catch(error => { logger('database', 'exec function error: ' + error.message); reject(error); }); }); }
the connection object wraps database connection object , provides generator function ability process rows of results database, won't post here (although example below using process rows).
here example of using exec function run sequence of sql
db.exec(function*(connection) { if (params.name === admin_user) { debug('admin logon'); user.name = admin_display; user.keys = 'a'; user.uid = 0; let sql = 'select passwordsalt admin adminid = 0'; connection.request(sql); yield connection.execsql(function*() { let row = yield; if (row) { user.nopass = (row[0].value === null); } else { user.nopass = false; } debug('admin password bypass ' + user.nopass.tostring()); }); } else { debug('normal user logon'); let sql = `select u.userid,passwordsalt,displayname,accesskey,l.logid users u left join userlog l on u.userid = l.userid , datediff(d,l.logdate,getdate()) = 0 u.username = @username`; let request = connection.request(sql); request.addparameter('username',db.types.nvarchar,params.name); let count = yield connection.execsql(function*() { let row = yield; if (row) { user.uid = row[0].value; user.name = row[2].value; user.keys = (row[3].value === null) ? '' : row[3].value; user.nopass = (row[1].value === null) ; user.lid = (row[4].value === null) ? 0 : row[4].value; debug('found user uid = %d , lid = %d, keys = %s', user.uid, user.lid, user.keys); } }); if (count === 0) { debug('not found user'); // couldn't find name in database reply(false,false); return; } } if (!user.nopass) { debug('need password'); //user has password must check passgood = false; //assume false go let request = connection.request('checkpassword'); request.addparameter('userid',db.types.int,user.uid); request.addparameter('password',db.types.varchar,params.password); yield connection.callprocedure(function*() { let row = yield; if (row) { //got valid row means have valid password passgood = true; } }); } else { passgood = true; } if (!passgood) { debug('not pasword'); reply(false,true); } else { if (user.uid !== 0 && user.lid === 0) { let sql = `insert userlog(userid,logdate,timeon,username) output inserted.logid values(@uid,getdate(),getdate(),@username)`; let request = connection.request(sql); request.addparameter('uid',db.types.int,user.uid); request.addparameter('username',db.types.nvarchar,user.name); yield connection.execsql(function*() { let row = yield; if (row) { user.lid = row[0].value; debug('users log entry = %d',user.lid); } }); } reply(true,user); } }) .catch((err) => { logger('database','error on logon: ' + err.message); reply(false,false); }); });
Comments
Post a Comment