Say that we have a function, getRandomDog
that runs a callback function asynchronously with a dog object as an argument:
const getRandomName = function() {
const names = ['puppy', 'buddy', 'sam'];
return names[Math.floor(Math.random() * names.length)];
};
const getRandomDog = function(callback) {
setTimeout(function() {
const dog = {
name: getRandomName(),
};
callback(dog);
}, Math.floor(Math.random() * 2000));
};
var dog = getDog();
console.log(dog);
(Give it a try before reading on)
// answer:
getRandomDog(function(dog) {
console.log(dog);
});
getRandomDog(function(dog1) {
console.log(dog1);
});
getRandomDog(function(dog2) {
console.log(dog2);
});
Answer: It's a trick question; We don't know which one gets logged first.
getTwoDogs
should use getRandomDog
twice, and call the callback with an array of two dogs in it as an argument. (The order of the dogs in the array does not matter)
const getTwoDogs = function(callback) {
//
// your code here
//
};
// example usage:
getTwoDogs(function(dogs) {
console.log(dogs); // [{ name: 'puppy' }, { name: 'sam' }]
});
Very Wrong Solution:
const getTwoDogs = function(callback) {
return [getRandomDog(), getRandomDog()];
};
Incorrect Solution:
const getTwoDogs = function(callback) {
const dog1 = getRandomDog();
const dog2 = getRandomDog();
callback([dog1, dog2]);
};
Naive Solution:
// answer
const getTwoDogs = function(callback) {
getRandomDog(function(dog1) {
getRandomDog(function(dog2) {
callback([dog1, dog2]);
});
});
};
Why is this naive? How could it be improved?
Efficient (but not clean) Solution:
// answer
const getTwoDogs = function(callback) {
const dogs = [];
getRandomDog(function(dog1) {
dogs.push(dog1);
if (dogs.length === 2) {
callback(dogs);
}
});
getRandomDog(function(dog2) {
dogs.push(dog2);
if (dogs.length === 2) {
callback(dogs);
}
});
};
Optimal Solution:
// answer
const getTwoDogs = function(callback) {
const dogs = [];
const handleNewDog = function(dog) {
dogs.push(dog);
if (dogs.length === 2) {
callback(dogs);
}
};
getRandomDog(handleNewDog);
getRandomDog(handleNewDog);
};
getNDogs
takes 2 arguments:
- a number,
n
, that specifies how many dogs to get - a callback function, which is called with an array of
n
dogs as its argument.
getNDogs = function(n, callback) {
//
// your code here
//
};
Based on optimal solution from getTwoDogs:
// answer
getNDogs = function(n, callback) {
const dogs = [];
const handleNewDog = function(dog) {
dogs.push(dog);
if (dogs.length === n) {
callback(dogs);
}
};
for (let i = 0; i < n; i++) {
getRandomDog(handleNewDog);
}
};