javascript Callbacks
When processing diferent task that are supposed to be executed in a specific order can be altered when a process take more time to do the job.
var output = '';
function task1(){
output += 'task1->';
}
function task2(){
output += 'task2->';
}
function task3(){
output += 'task3->';
}
task1();
task2();
task3();
console.log(output);
// output: task1->task2->task3->
when task take a little more time to finish each one the console.log(output) is executed before than the tasks.
var output = '';
function task1(){
setTimeout(() => {
output += 'task1->';
}, 0);
}
function task2(){
setTimeout(() => {
output += 'task2->';
}, 0);
}
function task3(){
setTimeout(() => {
output += 'task3->';
}, 0);
}
task1();
task2();
task3();
console.log(output);
// output: <empty string>
If the console.log is also executed in a little more time the update of output is perfectly reached.
var output = '';
function task1(){
setTimeout(() => {
output += 'task1->';
}, 0);
}
function task2(){
setTimeout(() => {
output += 'task2->';
}, 0);
}
function task3(){
setTimeout(() => {
output += 'task3->';
}, 0);
}
task1();
task2();
task3();
setTimeout(() => {
console.log(output);
}, 0);
// output: task1->task2->task3->
In the next case each task take a little more time that his previous one, and the console output only takes the changes till the task2.
var output = '';
function task1(){
setTimeout(() => {
output += 'task1->';
}, 10);
}
function task2(){
setTimeout(() => {
output += 'task2->';
}, 20);
}
function task3(){
setTimeout(() => {
output += 'task3->';
}, 30);
}
task1();
task2();
task3();
setTimeout(() => {
console.log(output);
}, 20);
// output: task1->task2->
But when the time taken for each task is not the same as the supossed order.
var output = '';
function task1(){
setTimeout(() => {
output += 'task1->';
}, 30);
}
function task2(){
setTimeout(() => {
output += 'task2->';
}, 10);
}
function task3(){
setTimeout(() => {
output += 'task3->';
}, 20);
}
task1();
task2();
task3();
setTimeout(() => {
console.log(output);
}, 30);
// output: task2->task3->task1->
To Ensure that the order excecution be the correct, we use callback functions to be executed inside their respective block code of setTimeout, so independently the time it takes to do the task always the task secuence will be in the desired order.
var output = '';
function task1(callback){
setTimeout(() => {
output += 'task1->';
callback();
}, 30);
}
function task2(callback){
setTimeout(() => {
output += 'task2->';
callback();
}, 10);
}
function task3(callback){
setTimeout(() => {
output += 'task3->';
callback();
}, 20);
}
task1( () => {
task2( () => {
task3( ()=>{}
)
})
});
setTimeout(() => {
console.log(output);
}, 100);
// output: task1->task2->task3->
Another way to do call the callback, notice the output timeout more than the sum of the timeout of the task to catch all the changes.
var output = '';
function task1(fn){
setTimeout(() => {
fn('task1->');
}, 30);
}
function task2(fn){
setTimeout(() => {
fn('task2->');
}, 10);
}
function task3(fn){
setTimeout(() => {
fn('task3->');
}, 20);
}
task1( m => {
output += m;
task2( m2 => {
output += m2;
task3( m3 => {
output += m3;
})
})
});
setTimeout(() => {
console.log(output);
}, 70);
// output: task1->task2->task3->
The same mechanism is used here to asure the correct order
const posts = [{title: 'post one', body: 'body of post one'},
{title: 'post two', body: 'body of post two'}];
function getPosts(){
setTimeout(() => {
let output = '';
posts.forEach( (post, index) => {
console.log(index + ' ' + post.title );
output += `<li>${post.title}</li>`;
});
document.body.innerHTML = output;}
,1000);
};
function createPost(post, callback){
setTimeout(() => {
posts.push(post);
callback();
},2000);
};
createPost({title: 'post three', body:'body of post three'}, getPosts);
Browser output:
Another example of callbacks with files
first the file basic
readfile.js
//readfile.js
var fs = require('fs')
function getRecord( filepath, done){
fs.readFile(filepath, function(err, data) {
if (err) return done(err)
data = data.toString().split('\r\n')
console.log(data)
})
}
getRecord('personas.txt')
To run this script, in the console type
>node readfile.js
> node readfiles.js
[
'Juan Perez',
'Luis Rogriguez',
'Karla Martinez',
'Luisa Miranda',
'Manuel Lopez',
'Jose Alberto'
]
[
'Juan Perez',
'Luis Rogriguez',
'Karla Martinez',
'Luisa Miranda',
'Manuel Lopez',
'Jose Alberto'
]
Now using callback
file personas.estudiantes
Luis Rogriguez
Luisa Miranda
Jose Alberto
Luisa Miranda
Jose Alberto
file personas.txt
Juan Perez
Luis Rogriguez
Karla Martinez
Luisa Miranda
Manuel Lopez
Jose Alberto
Luis Rogriguez
Karla Martinez
Luisa Miranda
Manuel Lopez
Jose Alberto
//index.js
var fs = require('fs')
function getPersonsStudents( filepath, done){
fs.readFile(filepath, function(err, persons){
if(err) return done(err)
fs.readFile('personas.estudiantes', function(err, students){
if(err) return done(err)
groupIntersection(persons, students)
})
})
function groupIntersection( persons, students){
students = students.toString().split('\r\n');
persons = persons.toString().split('\r\n').filter(function(person){
return students.indexOf(person) !== -1
})
done(null, persons)
}
}
getPersonsStudents('personas.txt', function(err, person){
console.log(person);
})
To run the script type
>node index.js
[ 'Luis Rogriguez', 'Luisa Miranda', 'Jose Alberto' ]
Another Sample, loading the following images in order are not guarantee
var persons = ['Jose Alberto','elena jimenez','Luisa Miranda']
var count = persons.length
persons = persons.map(function(person){
var img = new Image()
img.onload = function() {
next()
}
img.src = person + '.jpg'
return img
})
function next() {
count--
if (count < 1){
persons.forEach( function(person) {
console.log(person.width)
document.body.appendChild(person)
})
}
}
In this version the order is preserved on load by using recursivity.
var persons = ['Jose Alberto','elena jimenez','Luisa Miranda']
var images = []
function loadImages(){
var person = persons.shift()
if(!person){
console.log('All images loaded.', images)
return
}
var img = new Image()
img.onload = function(){
loadImages()
}
img.src = person + '.jpg'
images.push(img)
}
loadImages()
browser inspector output:
eot
No hay comentarios:
Publicar un comentario