function readFile(filePath) {
var filesystem = require('fs');
filesystem.readFile(filename, 'utf8', function(err, data) {
if (err) throw err;
console.log('OK: ' + filename);
console.log(data)
});
}
function fetchFromMemory(callback) {
setTimeout(function() {
callback('This is data from memory')
}, 3000);
};
function isError() {
return Math.floor((Math.random()*100)+1) % 2 == 0;
};
function fetchFromMemory(callback) {
if(isError()){
throw "Memory fetch failed";
}
setTimeout(function() {
callback('This is data from memory')
}, 3000);
};
function fetchFromRemoteCall(callback) {
if(isError()){
throw "Remote call failed";
}
setTimeout(function() {
callback('This is data from remote call')
}, 3000);
};
function readWrite() {
fetchFromMemory(function(memoryData) {
fetchFromRemoteCall(function(remoteCallData) {
console.log(memoryData + "-" + remoteCallData);
});
});
};
function readWrite() {
try{
fetchFromMemory(function(memoryData) {
try {
fetchFromRemoteCall(function(remoteCallData) {
printData(memoryData + "-" + remoteCallData);
});
}
catch(err){
console.error(err);
}
});
}
catch(err){
console.error(err);
}
};
function foo(){
doThis(function(){
doThat(function(){
doSomeMore(function(){
// Some more logic
})
});
});
};
function foo(){
doThis()
.then(function(){
doThat();
})
.then(function(){
doSomeMore();
})
.then(function(){
// Some more logic
});
};
function readWrite() {
try{
fetchFromMemory(function(memoryData) {
try {
fetchFromRemoteCall(function(remoteCallData) {
printData(memoryData + "-" + remoteCallData);
});
}
catch(err){
console.error(err);
}
});
}
catch(err){
console.error(err);
}
};
function readWrite() {
var memoryData;
fetchFromMemory()
.then(function(dataReadFromMemory) {
memoryData = dataReadFromMemory;
return fetchFromRemoteCall();
})
.then(function(dataReadFromRemote) {
printData(memoryData + "-" + dataReadFromRemote);
})
.fail(function(reason) {
console.error(reason);
});
};
But this restructuring of code can be achieved by using Promises
Promises are an abstraction for asynchronous programming. They are like proxies for an asynchronous computation. In future, they are evaluated into a desired value or an undesirable error.
https://github.com/kriskowal/qhttp://documentup.com/kriskowal/q
function readWritePromises() {
var memoryData;
fetchFromMemoryPromise()
.then(function(dataFromMemoryFetch) {
memoryData = dataFromMemoryFetch;
return fetchFromRemoteCallPromise();
})
.then(function(dataFromRemoteFetch) {
printData(memoryData + "-" + dataFromRemoteFetch);
})
.fail(function(reason) {
console.error(reason);
});
};
There is one thing above that most of us will hate
the variable memoryData
How could we get rid of it?
function readWriteWithSpread() {
fetchFromMemoryPromise()
.then(function(data) {
return [data, fetchFromRemoteCallPromise()];
})
.spread(function(memoryData, remoteData) {
printData(memoryData + "-" + remoteData);
})
.fail(function(reason) {
console.log(reason);
});
};
Though it is asynchronous, but this is still sequential
remote call won't happen until memory read finishes
Can we improve further?
function readWriteParallel() {
var memoryPromise = fetchFromMemoryPromise();
var remotePromise = fetchFromRemoteCallPromise();
Q.all([memoryPromise, remotePromise])
.spread(function(memoryData, remoteData) {
printData(memoryData + "-" + remoteData);
})
.fail(function(reason) {
console.log(reason);
});
};
Well, it's actually not in parallel
But one promise does not have to wait for other promise to be fulfilled
function fetchFromMemoryPromise() {
var deferred = Q.defer();
setTimeout(function() {
if(isError()){
deferred.reject("Memory fetch failed");
}else{
deferred.resolve('This is data from memory');
}
}, 3000);
return deferred.promise;
};
Create a deferred object
Resolve the deferred on success condition
Reject the deferred on failure condition
Create a promise from deferred and return the promise