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

Popular posts from this blog

gridview - Yii2 DataPorivider $totalSum for a column -

java - Suppress Jboss version details from HTTP error response -

Sass watch command compiles .scss files before full sftp upload -