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 actions 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