Reputation: 1757
I have three functions that I want to use promises to force them to execute in order.
function 1 sends a http request, fetches JSON data and saved it to a file function 2 loops through that file and updates the database according the difference values/values missing function 3 will loop through the newly updated database and create a 2nd json file.
Currently function 1 works perfectly on its own with a setInterval of 30 minutes.
I want to start function 2 when function 1 has finished. then function 3 after function 2 has finished.
Using promises I am trying to attach function 2 to a simple finished log to understand how to use promises but not getting much success. The items from the for loop log but my Finished/err log before my for loop which shouldn't be happening. Any suggestions?
function readJson() {
return new Promise(function() {
fs.readFile(__dirname + "/" + "bitSkin.json", 'utf8', function read(err, data) {
if (err) { throw err; }
var bitCon = JSON.parse(data);
for(var i=0; i<7; i++) { //bitCon.prices.length; i++) {
var price = bitCon.prices[i].price
var itemName = bitCon.prices[i].market_hash_name;
(function() {
var iNameCopy = itemName;
var priceCopy = price;
logger.info(iNameCopy);
}());
}
});
});
};
function fin() {
logger.info("Finished");
}
readJson().then(fin(), console.log("err"));
Upvotes: 2
Views: 172
Reputation: 707376
Promises have no magical powers. They don't magically know when async code inside them is done. If you create a promise, you yourself have to resolve()
or reject()
it when the async code has an error or completes.
Then, in addition, you have to pass a function reference to a .then()
handler, not the result of executing a function. .then(fin())
will call fin()
immediately and pass it's return value to .then()
which is not what you want. You want something like .then(fin)
.
Here's how you can resolve and reject the promise you created:
function readJson() {
return new Promise(function(resolve, reject) {
fs.readFile(__dirname + "/" + "bitSkin.json", 'utf8', function read(err, data) {
if (err) { return reject(err); }
var bitCon = JSON.parse(data);
for(var i=0; i<7; i++) { //bitCon.prices.length; i++) {
var price = bitCon.prices[i].price
var itemName = bitCon.prices[i].market_hash_name;
(function() {
var iNameCopy = itemName;
var priceCopy = price;
logger.info(iNameCopy);
}());
}
resolve(bitCon);
});
});
};
And, you could use that like this:
function fin() {
logger.info("Finished");
}
readJson().then(fin, function(err) {
console.log("err", err)
});
Summary of changes:
reject(err)
when there's an errorresolve()
when the async code is done..then()
handlers.FYI, when creating a promise wrapper around an async function, it is generally better to wrap just the function itself. This makes the wrapper 100% reusable and puts more of your code in the promise architecture which generally streamlines things and makes error handling easier. You could fix things up that way like this:
fs.readFilePromise = function(file, options) {
return new Promise(function(resolve, reject) {
fs.readFile(file, options, function(err, data) {
if (err) return reject(err);
resolve(data);
});
});
};
function readJson() {
return fs.readFilePromise(__dirname + "/" + "bitSkin.json", 'utf8').then(function(data) {
var bitCon = JSON.parse(data);
bitCon.prices.forEach(function(item) {
logger.info(item.market_hash_name);
});
return bitCon;
});
}
Upvotes: 4