Forked from shimondoodkin/1-callback basics tutorial.js
Created
June 12, 2013 07:29
-
-
Save ilmsg/5763440 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
the basics of programming with callbacks: | |
structure: | |
function simple1(cb) // the last argument is callback function | |
{ | |
if(cb)return cb();// the return is required to prevent continuation of the function. | |
// the if(cb) is optional and it is to enable to omit the callback in rare cases. it is usually useful in api functions. | |
} | |
to make a function asynchronous capbl;e: | |
add cb as last argument. | |
put at the end: if(cb)return cb(); | |
the callback function: | |
simple form: | |
function(data){} | |
standard form: | |
function(error,data){} // when there is no error. error usually contains null or maybe undefined | |
// with null as error | |
function simple2(a,b,cb) | |
{ | |
if(b==0) return cb(new Error('error description')); | |
var data=a/b; | |
if(cb)return cb(null,data); | |
} | |
usage: | |
// | |
simple2(1, 3, function(err,data) { | |
if(error){ | |
throw error; | |
// or do something else like | |
console.log(error.stack) | |
return; | |
} | |
console.log('data=',data) | |
}); | |
passing the callback on to next function: | |
function simple3(a,b,cb) | |
{ | |
a++; | |
return simple2(a,b,cb); | |
} | |
using anonymous function to pass arguments as closure: | |
function simple3_version2(a,b,cb) | |
{ | |
var preva=a; | |
a++; | |
return simple2(a,b,function(err,data){ if(cb) cb(err,data,preva)}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//use the name cb all over the place and it just works: | |
var async=require('async'); | |
var items=[1,2,3] | |
function calc(a,cb) { | |
cb(a*a) | |
} | |
function simple4(items,cb) | |
{ | |
var results={}; | |
async.eachLimit(items,4,function(item,cb) | |
{ | |
result[k]=calc(item,cb) // pass the inner cb of for each | |
}, | |
function(){ | |
console.log('done all'); | |
cb(results); // function cb | |
}); | |
} | |
// another example: | |
function simple4_b(items,cb) | |
{ | |
var results={}; | |
async.parallel( | |
[ | |
function(cb) { | |
console.log('1'); | |
cb() // inner cb | |
} | |
, | |
function(cb) { | |
console.log('1'); | |
cb() // inner cb | |
} | |
] | |
, | |
function(){ | |
console.log('done all'); | |
cb(); // function cb | |
} | |
); | |
} | |
// a shortcut cb | |
function simple5(items,cb1) | |
{ | |
var results={}; | |
function cb(){cb1(results)} // sometimes people call the function next instead of cb | |
async.eachLimit(Object.keys(items),4,function(k,cb) | |
{ | |
var item=items[k] | |
result[k]=calc(item,cb) | |
},function(){ | |
console.log('done all'); | |
cb(); | |
}); | |
} | |
//while loop: | |
function simple6(times,cb) | |
{ | |
function loop() | |
{ | |
times--; | |
if(times==5)return loop();// use return iterator() as continue | |
// do something here | |
if(times>0)return loop(); else return cb()// use return cb() as break | |
} | |
if(times>0)loop(); else cb() | |
} | |
// retry | |
//from this: | |
function simple7(options,cb) | |
{ | |
do_async_request(options,function(err,data){ | |
if(err){ | |
console.log('simple7 - error, faild',err.stack,options); | |
return; | |
} | |
//do work with data | |
}) | |
} | |
//to this: | |
// 1. wrap everything inside with a local function and call this function. | |
// 2. add some retry code | |
function simple7_with_retry(options,cb) | |
{ | |
var retries=0; | |
function retry() | |
{ | |
do_async_request(options,function(err,data){ | |
if(err){ | |
if(retries<7) | |
{ | |
retries++; | |
console.log('simple7 - error, retrying',err.stack,options); | |
setTimeout(retry,3000) | |
return; | |
} | |
else { | |
console.log('simple7 - error, faild',err.stack,options); | |
return; | |
} | |
} | |
//do work with data | |
}) | |
} | |
retry() | |
} | |
//use the name cb all over the place and it just works: | |
var async=require('async'); | |
var items=[1,2,3] | |
function calc(a,cb) { | |
cb(a*a) | |
} | |
// you can iterate keys if you like to: | |
// use iterate keys to iterate parallel objects parallely sinchroniously or use the key for something else | |
var async=require('async'); | |
function calc(a,cb) { | |
cb(a*a) | |
} | |
var item_names=["a","b","c"] | |
var item_value=[1,2,3] | |
function simple4(cb) | |
{ | |
var results={}; | |
var items_keys=Object.keys(item_names) | |
async.eachLimit(items_keys,4,function(k,cb) | |
{ | |
var name=item_names[k] | |
var value=item_value[k] | |
result[k]=name+' '+calc(value,cb) | |
},function(){ | |
console.log('done all'); | |
cb(results); | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#file-1-callback-basics-tutorial-js-L10 | |
Benjamin Gruenbaum asked to clerify: | |
using callback doesn't turn a function to asynchronious, just into asynchronious capble. | |
asynchronious means the callback is executed by the system or as response to an outside event | |
like to setTimeout or when data read from disk is ready. | |
writing functions with a callback enables to use asynchronious functions inside your code. | |
#file-1-callback-basics-tutorial-js-L12 | |
the short form is if(cb)cb() | |
when i type i start by adding cb as the last argument, then i add before end of the function if(cb)cb(); | |
then after writing the function i check the code and return before cb() | |
adding return is helpful to prevent unexpected errors, which occur if the callback is inside a conditional statment (if,for,while,...) or there is code after the function. just because I am lazy to hard to debug errors later. usually i just write if(cb)return cb(); every time. except when it is obvious that it is not needed. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment