I am using async parallel to get data from db in parallel.
When every task is returning the data I am storing it in local object.
From index.js I am calling cacheService.js .
In cacheService.js I am loading data from mysql database and mongo database in to cache object.
Whenever I am doing npm run local run. I am getting following error.
UNHANDLEDREJECTION Error: Callback was already called.
This error is coming from loadMongoData method of cacheService.js.
I have followed other answers on stackoverflow like adding else part
Here is code for cacheService.js.
'use strict';
var cache = [];
class cacheService {
async init() {
await this.loadMongoData();
}
loadMongoData(env, callback1) {
const _this = this;
console.log('Inside loadMongoData')
async.parallel(
{
task1: function (callback) {
CriteriaDef.find({})
.lean()
.exec(function (err, criteriaDefs) {
if (err) {
console.log('Inside err 1')
logger.error('Error fetching CriteriaDef: ', util.inspect(err));
callback(err, null);
} else if (criteriaDefs) {
console.log('Inside criteriaDefs')
if (criteriaDefs.length && criteriaDefs.length > 0) {
console.log('Inside criteriaDefs 1')
global.CRITERIA_DEFS = criteriaDefs;
cache['criteria_defs'] = criteriaDefs;
}
callback(null, null);
}
});
},
task2: function (callback) {
groupDef
.find({})
.lean()
.exec(function (err, groupDefs) {
if (err) {
console.log('Inside err2')
logger.error('Error fetching groupDefs: ', util.inspect(err));
callback(null, err);
} else if (groupDefs) {
console.log('Inside ')
global.groupDefsWithRoles = groupDefs;
let _groupDefs = [];
_.each(groupDefs, function (groupDef) {
var data = {
value: groupDef._id,
label: `${groupDef._id}: ${groupDef.description}`
};
_groupDefs.push(data);
});
global.groupDefs = _groupDefs;
cache['groupDefs'] = _groupDefs;
logger.info('Loaded groupDefs: ', global.groupDefs.length);
callback(null, null);
}
});
},
task3: function (callback) {
jiraProjects.find({$or: [{archived: {$ne: true}}, {archived: {$exists: false}}]}).exec(function (err, jiraProjects) {
if (err) {
console.log('Inside error 3')
logger.error('Error fetching jiraProjects: ', err);
callback(null, err);
} else if (jiraProjects) {
console.log('Inside jira project')
let _jiraProjects = [];
_.each(jiraProjects, function (jiraProject) {
var data = {
value: jiraProject.key,
label: jiraProject.key,
issueType: jiraProject.issueType ? jiraProject.issueType : 'Bug'
};
_jiraProjects.push(data);
});
global.jiraProjectsList = _jiraProjects;
cache['jiraProjects'] = _jiraProjects;
logger.info('Loaded jira projects: ', global.jiraProjectsList.length);
callback(null, null);
}
});
},
task4: function (callback) {
console.log('Inside task4')
callback(null, null);
},
task5: function (callback) {
inputElements
.find({})
.lean()
.exec(function (err, inputElements) {
if (err) {
console.log('Inside error5')
logger.error('Error fetching inputElements: ', util.inspect(err));
callback(null, err);
} else if (inputElements) {
console.log('Inside inputelements')
global.INPUT_ELEMENTS_DEF = inputElements;
cache['INPUT_ELEMENTS_DEF'] = inputElements;
callback(null, null);
}
});
},
task6: function (callback) {
console.log('Inside task6')
sisp.loadProducts('', callback);
}
},
function (err, results) {
if (err) {
console.log('Inside final error')
logger.error("Something went wrong can't start the app: ", util.inspect(err));
callback1(null, err);
} else {
console.log('Inside final else')
logger.info('loaded all globals properly :)');
callback1(null, null);
}
}
)
}
}
export default new cacheService();
I think your problem cuz you use callback inside of promise.
Please change your code like this:
class cacheService {
async init() {
await new Promise((resolve, reject) => {
this.loadMongoData(env, (ignoreArg, error) => {
if (error) {
return reject(error);
}
resolve();
});
});
}
...
}
Tip: in the each task add statement else for call callback, because maybe your statement not handled and your code can't execute prefect
task1: function (callback) {
CriteriaDef.find({})
.lean()
.exec(function (err, criteriaDefs) {
if (err) {
console.log('Inside err 1')
logger.error('Error fetching CriteriaDef: ', util.inspect(err));
callback(err, null);
} else if (criteriaDefs) {
console.log('Inside criteriaDefs')
if (criteriaDefs.length && criteriaDefs.length > 0) {
console.log('Inside criteriaDefs 1')
global.CRITERIA_DEFS = criteriaDefs;
cache['criteria_defs'] = criteriaDefs;
}
callback(null, null);
} else {
callback(null, null);
}
});
},
Related
I'm new to Javascript. I want to make this block run after the if statement is finished (asynchronous). The reason I want that is that I want to make some changes to update them if it falls into the if statement
let params = {
TableName: "storepedia-test",
Item: updatedItem
};
docClient.put(params, function (err, data) {
if (err) {
console.log(err);
} else {
res.redirect('/devices');
}
});
Here is my whole code
const { id } = req.params;
const file = req.file;
let updatedItem = { ...req.body};
updatedItem.id = id;
if (file !== undefined){
const deleteParams = {
Key: updatedItem.image,
Bucket: bucketName
}
s3.deleteObject(deleteParams, async (err, data) => {
if (err) {
console.log(err)
} else {
const result = await uploadFile(file);
console.log('result', result);
await unlinkFile(file.path);
updatedItem.image = result.Key;
let params = {
TableName: "storepedia-test",
Item: updatedItem
};
docClient.put(params, function (err, data) {
if (err) {
console.log(err);
} else {
res.redirect('/devices');
}
});
}
})
}
let params = {
TableName: "storepedia-test",
Item: updatedItem
};
docClient.put(params, function (err, data) {
if (err) {
console.log(err);
} else {
res.redirect('/devices');
}
});
Just to run something after the if? I think this is the best spot:
docClient.put(params, function(err, data) {
if (err) {
console.log(err);
} else {
// run async code here.
// when done do the redirect.
// for example:
s3.do_something(function(err, data) {
if (err) {
console.log(err)
} else {
console.log(data)
res.redirect('/devices');
}
})
}
});
why is that ReferenceError: err is not defined even though it is defined here?
const sampleObject = require('./sampleObject');
const sampleModel = (callback) => {
if (true) {
sampleObject.sampleRetrieval(err, data => {
if (err) {
callback(err)
} else {
callback(data)
}
})
} else {
console.log('Something went wrong.');
}
}
module.exports = sampleModel;
This is the file that executes the query and passes it to the sampleModel.
const myDB = require('../db/database');
module.exports = {
sampleRetrieval: () => {
let sql = "SELECT * FROM ACCOUNTS";
myDB.query(sql, (err, data) => {
if (err) {
callback(null, err)
} else {
callback(err, data)
}
})
}
}
Error : err is not defined
newUser.save()
.then( ()=> res.json('User added!'))
.catch( err => res.status(400).json('Error: '+ err));
Fixed
newUser.save()
.then( ()=> res.json('User added!'))
.catch( (err) => res.status(400).json('Error: '+ err));
The problem is that your function sampleRetrieval is not receiving a callback function as a parameter. It should be something like this:
sampleRetrieval: (callback) => {
let sql = "SELECT * FROM ACCOUNTS";
myDB.query(sql, (err, data) => {
if(err) {
callback(null, err);
} else {
callback(err, data);
}
})
}
And then fix the parentheses like the comment of Dan O says:
const sampleModel = (callback) => {
if (true) {
sampleObject.sampleRetrieval((err, data) => {
if (err) {
callback(err)
} else {
callback(data)
}
})
} else {
console.log('Something went wrong.');
}
}
Hope it helps!
I want to integrate Stripe into my application. I have collected all necessary Data in the req.body.
Now an undefined error is being thrown after creating the customer Id and while trying to pass it to addCustomerToCard. After that, createToken is being successfully logged.
So two questions:
1.Why is the order of functions not being invoked as I would expect?
2.Why does the customer not get passed in addCustomerToCard?
router.post("/checkout", async function (req, res, next) {
if (!req.session.cart) {
return res.redirect("/shopping-cart");
}
let createCustomer = function () {
var param ={};
param.email = req.body.email;
param.name= req.body.name;
param.description ="";
return stripe.customers.create(param, function (err, customer) {
if (err) {
console.log("err:" + err);
}
if (customer) {
console.log("success: " + JSON.stringify(customer, null, 2));
} else {
console.log("something went wrong");
}
});
};
let createToken = function () {
let param ={};
param.card = {
number: req.body.card,
exp_month: req.body.exp_month,
exp_year: req.body.exp_year,
cvc: req.body.security
}
return stripe.tokens.create(param, function (err, token) {
if (err) {
console.log("err:" + err);
console.log(param);
}
if (token) {
console.log("success: " + JSON.stringify(token, null, 2));
console.log(req.body);
} else {
console.log("something went wrong");
}
});
};
let addCardToCustomer = function () {
console.log(createdCustomer);
return stripe.customers.createSource(customer.id, {source: token.id}, function (err, card) {
if (err) {
console.log("err:" + err);
console.log(param);
}
if (card) {
console.log("success: " + JSON.stringify(card, null, 2));
} else {
console.log("something went wrong");
}
});
};
let chargeCustomerThroughCustomerID = function () {
let param = {
amount: cart.totalPrice,
currency: 'eur',
description: 'First payment',
customer: customer.id
}
stripe.charges.create(param, function (err, charge) {
if (err) {
console.log("err: " + err);
}
if (charge) {
console.log("success: " + JSON.stringify(charge, null, 2));
} else {
console.log("Something wrong")
}
})
}
try {
const createdCustomer = await createCustomer(); // promise 1
const createdToken = await createToken();
const addedCardToCustomer = await addCardToCustomer(createdCustomer,createdToken ); //
// const chargeCustomerThroughCustomerID = await chargeCustomerThroughCustomerID(); // promise 4
res.send("success");
} catch (e) {
console.log(`error ${e}`)
};
});
//LOG OUTPUT
//success
//error ReferenceError: createdCustomer is not defined
//success
You should break this down into smaller pieces to verify the behaviour you're expecting, for starters. There's quite a lot going on here.
One problem is that you are trying to await functions which are not async -- you should have each function marked:
let createCustomer = async function () {...}
This is likely the reason the sequence is not what you expect.
You're hitting an error in addCardToCustomer because createCustomer is undefined in the scope of that function. You need to have a parameter:
let addCardToCustomer = async function (createdCustomer) { ... }
MongoClient.connect's callback does not invoke
I try to invoke the callback in aws lambda but it doesn't work, however if I remove exports.lambdaHandler and just invoke it by node app.js it works just fine.
exports.lambdaHandler = async (event, context) => {
try {
MongoClient.connect(url, {
useNewUrlParser: true
}, (err, client) => {
console.log("Connected successfully to server");
});
response = {
'statusCode': 200,
'body': JSON.stringify({
message: 'test'
})
}
return response
} catch (err) {
console.log(err);
return err;
}
};
should return
Connected successfully to server
edit
I changed it to await instead. now it's good
exports.lambdaHandler = async (event, context) => {
try {
const client = await MongoClient.connect(url, {
useNewUrlParser: true
})
const db = client.db(dbName)
await db.createCollection(collectionName)
client.close()
return {
'statusCode': 200,
'body': JSON.stringify({
message: 'test'
})
}
} catch (err) {
console.log(err);
return err;
}
};
Try this, it would return the results else throw an error which will be caught below and returned by Lambda
exports.lambdaHandler = async (event, context) => {
try {
MongoClient.connect(url, {useNewUrlParser: true}, (err, client) => {
if (err) { console.log(err); throw(err); }
else {
console.log("Connected successfully to server");
console.log(client);
response = {
'statusCode': 200,
'body': JSON.stringify({message: client})
};
return response;
};
});
} catch (err) {
console.log(err);
return err;
}
};
I use Async utility module in my app. I have a question. How i can restart the async.series, when "get_data" stage return an error?
function get() {
console.log('App start');
async.series([
open_db,
get_data,
close_db
], function (err) {
console.log('App down');
})
};
function open_db(callback) {
mongoose.connect('mongodb://localhost/app', function (err) {
if (err) throw err;
console.log('App connect to DB');
callback();
});
};
function get_data(callback) {
if (err) {
console.log('Error')
callback();
} else {
console.log('Ok');
callback();
}
};
function close_db(callback) {
mongoose.disconnect(function() {
console.log('App disconnect from DB');
callback();
});
};
On "get_data" stage i use websockets.subscribe operations, and save data from another server to DB. When websocket connection down, i need to retry connection to server with some time interval
function query_data() {
async.series([
open_db,
get_data,
close_db
], function (err) {
if (err)
...
})
};
function open_db(callback, attempt_no) {
mongoose.connect('mongodb://localhost/app', function(err) {
if (!err)
return callback();
attemp_no = !attempt_no ? 1 : attempt_no + 1;
if (attempt_no > 5)
return callback(new Error('Maximum number of attempts exceeded'));
setTimeout(() => open_db(callback, attempt_no), 500);
});
};
function get_data(callback) {
if (err)
return callback(err);
// do-smth-with-data and call callback
};
function close_db(callback) {
mongoose.disconnect(callback);
};
Use async.retry
function all_get_data(cb) {
console.log('App start');
async.series([
open_db,
get_data,
close_db
], function (err) {
if (err) {
console.log('App down');
return cb(err)
}
return cb()
})
};
// try calling apiMethod 3 times, waiting 200 ms between each retry
async.retry({times: 3, interval: 200}, all_get_data, function(err, result) {
// do something with the result
});