Reputation: 55
I have a code like this
var fs = require('fs');
console.log("1");
fs.readFile("./index.js", function(err, data) {
if (err) {
console.log("err");
}
console.log("2");
});
console.log("3");
and the result will be
1
3
2
But I want 1 2 3
I have look through filesystem's document and it says With the asynchronous methods there is no guaranteed ordering.
so the document says if I want my code result 1 2 3
it should be
var fs = require('fs');
console.log("1");
fs.readFile("./index.js", function(err, data) {
if (err) {
console.log("err");
}
console.log("2");
console.log("3");
});
But it's for short code if I'm building a system which has a lot of other function needs to be after this code we can't nested all in because the function need to be work after it will be use by other functions so is there a way to let the fs.readFile
work in order but not incuding all the code need to work after it in fs
code?
function servedatastart() {
if (urlcontentbasic(urlslug) != "err") {
responsearray["data"] = urlcontentbasic(urlslug);
} else {
// callback function
console.log("urlex");
urlex("none", urlslug); // this function I use fs.readFile(urlslug, function...
}
console.log("other function");
//other function
cuswriteheader();
includescript();
writefooter()
res.end();
}
Upvotes: 1
Views: 1080
Reputation: 707278
The simple solution is to just put the rest of your code that you want to execute after the fs.readFile()
operation into a function and then insert that function into the async callback:
var fs = require('fs');
console.log("1");
fs.readFile("./index.js", function(err, data) {
if (err) {
console.log("err");
}
console.log("2");
moreCode();
});
function moreCode() {
console.log("3");
}
A bit more modern design is to use promises for all your asynchronous operations and then you can sequence things a bit easier.
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
console.log("1");
fs.readFileAsync("./index.js").then((data) => {
console.log("2");
return moreCode();
}).catch((err) => {
// handle error here
});
function moreCode() {
console.log("3");
}
Where the benefit of using promises really starts to take advantage is when you have multiple asynchronous operations that you want to sequence and each one returns a promise. Then, you can do that like this:
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
fs.readFileAsync("./index.js")
.then(moreCode1)
.then(moreCode2)
.catch((err) => {
// handle error here
});
Using the code you've show for the urlex()
function, here's how you can make all that work using promises:
// include infrastructure to automatically promisify the fs module
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
function servedatastart() {
Promise.resolve().then(function() {
if (urlcontentbasic(urlslug) != "err") {
// I'm assuming that urlcontentbasic is also async and returns a promise
// like urlexbasic does
return urlcontentbasic(urlslug);
} else {
// callback function
console.log("urlex");
return urlex("none", urlslug);
}
}).then(function() {
console.log("other function");
//other function
cuswriteheader();
includescript();
writefooter()
res.end();
});
}
// basic function for reading extension-less URL
// returns a promise whose resolved value is a returnarray data structure
function urlexbasic(filetype, slug) {
var returnarray = {status:null,contenttype:null,data:null,message:undefined};
if (slug == undefined) {
slug = "";
}
if (filetype == "none") {
var filename;
console.log("path: "+pathdataarray["1"]);
if (pathdataarray["1"] == "/pre") {
console.log("substr");
filename = urlslug.substr(4, urlslug.length-5);
console.log("1: "+filename);
}
urldata(q.pathname, "");
console.log("slug: "+ slug+" filename: "+ filename);
if (slug != "" || filename != undefined) {
console.log("what?")
if (filename != undefined) {
filename = "." + filename;
} else {
filename = "." + slug;
}
console.log("2: "+filename);
} else {
filename = "." + urlslug.substr(0, urlslug.length-1);
}
console.log("filename: "+ filename);
return fs.readFileAsync(filename.substr(0, filename.length-1), 'utf8').then(function(data) {
console.log("readfile");
var mime = null;
if (urldataarray.extension == "js") {
mime = "javascript";
} else {
mime = urldataarray.extension;
}
console.log("hey running");
returnarray["status"] = 200;
returnarray["contenttype"] = 'text/'+mime;
//res.writeHead(200, {'contenttype': 'text/'+mime});
returnarray["data"] = data;
console.log("instatus: "+returnarray["status"]);
// make returnarray be the resolved value of the promise
return returnarray;
}).catch(function(err) {
console.log("404 error");
returnarray["status"] = 404;
});
} else {
urldata(q.pathname, filetype);
var filename;
if (pathdataarray["1"] == "/pre") {
console.log("substr");
filename = urlslug.substr(4, urlslug.length-5);
console.log("11: "+filename);
}
console.log("2slug: "+ slug+" filename: "+ filename);
if (slug != "" || filename != undefined) {
if (filename) {
filename = "." + filename + "." + filetype;
} else {
filename = "." + slug +"."+ filetype;
}
console.log("22: "+filename);
} else {
filename = "." + urlslug.substr(0, urlslug.length-1) + "." + filetype;
}
return fs.readFileAsync(filename, 'utf8').then(function(data) {
var mime = null;
if (urldataarray.extension == "js") {
mime = "javascript";
} else {
mime = urldataarray.extension;
console.log("ok");
};
if (pathdataarray["1"] == "/pre") {
returnarray["status"] = 200;
returnarray["contenttype"] = 'text/plain';
//res.writeHead(200, {'contenttype': 'text/plain'});
//res.write("<pre><code>");
returnarray["data"] = data;
//res.write("</code></pre>");
} else {
returnarray["status"] = 200;
returnarray["contenttype"] = 'text/'+mime;
//res.writeHead(200, {'contenttype': 'text/'+mime});
console.log("pure data");
returnarray["data"] = data;
}
// make returnarray be the resolved value of the promise
return returnArray;
}).catch(function(err) {
return urlex(dataerrcall[filetype]);
});
}
}
// returns a promise whose resolved value is a returnArray
function urlex(filetypeex, slugex) {
//console.log(urlexbasic(filetypeex, slugex));
return urlexbasic(filetypeex, slugex).then(function(returnArray) {
console.log("return: "+returnarray.status);
responsearray["status"] = returnarray["status"];
responsearray["contenttype"] = returnarray["contenttype"]
responsearray["message"] = returnarray["message"];
responsearray["data"] = returnarray["data"];
return responsearray;
});
}
This uses several nice promise features such as chaining (to sequence async operations).
Upvotes: 1
Reputation: 756
Use async.waterfall, it allows you to run asynchronous functions in order, each function depends on the previous one to complete. when the last function completes the main callback is called, each function can pass the result to the next one. check https://caolan.github.io/async/docs.html
var fs = require('fs');
var async = require('async');
async.waterfall([
function (callback) {
console.log("1");
callback();
},
function (arg1, callback) {
fs.readFile("./index.js", callback);
console.log("2");
},
function (arg2, callback) {
console.log("3");
callback()
}
], function(err, res){
});
Upvotes: 4