I am using Node's async/await syntax,
I am trying to promisify a MySql function using Node's util library.
When trying to promisify mysql's begin transaction method,
I am getting the following error -
TypeError [ERR_INVALID_ARG_TYPE]: The "original" argument must be of type Function. Received type undefined
Code snippet -
let connection = requestBody.mysqlConnection;
try {
let createTransaction = util.promisify(connection.beginTransaction).bind(connection);
await createTransaction();
let insertQuery = util.promisify(connection.query).bind(connection);
let queryResponse = await insertQuery(sqlQuery, sqlData);
await connection.commit();
await connection.end();
response.insertId = queryResponse.insertId;
response.hasError = false;
return response;
} catch (error) {
console.log("RDS MySql Error : ", error);
await connection.rollback();
await connection.end();
response.hasError = true;
response.error = error;
return response;
}
Error trace -
Bind your mysql function before to promisify it, take a look on this small example:
const util = require('util')
function mysqlFn(params, callbk) {
callbk(null, true)
}
// bind first to make sure the first param is the callback after promisify the function
const mysqlFnBind = mysqlFn.bind(null, {param: 1})
const mysqlFnAsync = util.promisify(mysqlFnBind)
mysqlFnAsync().then(console.log)
Related
I was wondering what is a proper way to handle errors from async functions when dealing with MySQL and Middleware in an MVC express API.
//MODEL deleteRecipe.js
const del = async function(id){
let sql = "DELETE..."
try{
const [rows] = await promisePool(sql)
return true
}catch(err){
return new Error();
////or even JUST return false?
}
}
or
//MODEL deleteRecipe.js
const del = async function(id){
let sql = "DELETE..."
try{
const [rows] = await promisePool(sql)
return true;
}catch(err){
return Promise.reject('Something here');
////or even JUST return false?
}
}
to
CONTROLLER
const deleteRecipe = async function(req,res,next){
try{
const deleteResult = await recipeModel.del(is)
next();
}catch(err){
next(/*apiCustomError*/)
}
}
So the problems are :
Should return(true || false) and deal with error inside the model, or to return throw error like a hot potato to parent function (and how to do it properly?). Is try catch in the MODEL function necessary?
I know this might be a preference, but what's a better approach and why.
Thank you for your time and answers!
Here I am working on node js typescript and mysql api, after excecuting my api showing undefined.
if i check using console in params variable i am getting result
like this in terminal
[
1,
'2023-02-09T12:27:09+05:30',
'2023-02-09T12:27:09+05:30',
'jaga78',
'988888888',
'jagadeeshwaran907#gmail.com',
'123',
'0'
]
if i check console using 2nd variable addedUser showing undefined
here i have attached my api
const loginemail = async (req: Request, data:any ) => {
const connection = await createConnection()
try {
let sqlQuery = `INSERT INTO account (status,created_date,updated_date,username,phone,email,password,verified) VALUES (?,?,?,?,?,?,?,?)`
const params = [data.accountStatus,moment().format(),moment().format(),data.userName, data.Phone, data.accountEmail, data.Password,"0"]
const addedUser:any = await connection.execute(sqlQuery, params);
return {success: "success"}
} catch (error) {
await connection.end()
throw error
}
}
The following TypeScript function will retrieve data from a web API and display it to the console from within the function, but when I try to return the data object (a string) I get an error. I am trying to return the JSON data object by return data; but the compiler thinks I am not returning anything. Please, what am I doing wrong?
async function main(url: string, query: string): Promise<string> {
const axios = require('axios');
axios.get(url, {params: {"query": query}})
.then(function (response: any) {
let data = JSON.stringify(response.data);
console.log("data: " + data);
return data;
})
.catch(function (error: any) {
console.log(error);
return "error";
});
}
var url: string = 'https://api.subquery.network/sq/AcalaNetwork/karura-tokens';
var query = "{accountBalances (first: 5) {nodes{id accountId tokenId total}}}"
var res = main(url, query).catch(e => console.error(e)).finally(() => process.exit(0))
console.log("res:" + res);
Here is the output:
src/index.ts:1:50 - error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
1 async function main(url: string, query: string): Promise<string> {
In my example I am trying to return a string, but I am happy returning either a string or a JSON object. I just can't get either one to work.
One possible solution (a bit hacky) is to return the promise from your function, declare your res variable in the global scope and, in the promise callback, assign the value the promise resolves to res.
But the actual assignment will only happen after the promise resolves, so you might set a timeout to use the variable outside the promise callback.
For example:
function get_sq(url: string, query: string): Promise<any>{
const axios = require('axios');
return axios.get(url, {params: {"query": query}});
}
var url: string = 'https://api.subquery.network/sq/AcalaNetwork/karura-tokens';
var query = "{accountBalances (first: 5) {nodes{id accountId tokenId total}}}"
var res;
get_sq(url, query).then(function (response: any) {
res = JSON.stringify(response.data);
}).catch(function (error: any) {
res = error;
});
setTimeout(() => {console.log("res:" + res);}, 3000);
Another possibility (the more robust one) is to keep inside the promise callback and do what you want to do with res there.
I've just started messing about with GraphQL, and I'd like a resolver that uses a JSON file on disk as the data source. What I've got so far causes GraphQL to return null.
How do I do this and why doesn't the approach below work?
var schema = buildSchema(`
type Experiment {
id: String
trainData: String
goldData: String
gitCommit: String
employee: String
datetime: String
}
type Query {
# Metadata for an individual experiment
experiment: Experiment
}
schema {
query: Query
}`);
var root = {
experiment: () => {
fs.readFile('./data/experimentExample.json', 'utf8', function(err, data) {
if (err) throw err;
console.log(data);
return JSON.parse(data);
});
}
};
const app = express();
app.use('/graphql', graphqlHTTP({
rootValue: root,
schema: schema,
graphiql: true
}));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');
The callback function you're passing to readFile runs asynchronously, which means returning a value from it doesn't do anything -- the function the readFile call is inside is done executing and has returned a value (null) by the time your callback is done.
As a rule of thumb, when dealing with GraphQL, you should stay away from callbacks -- your resolvers should always return a value or a Promise that will eventually resolve to a value.
Luckily, fs has an asynchronous method for reading files, so you can just do:
const root = {
experiment: () => {
const file = fs.readFileSync('./data/experimentExample.json', 'utf8')
return JSON.parse(file)
}
};
// or even cleaner:
const root = {
experiment: () => JSON.parse(fs.readFileSync('./data/experimentExample.json', 'utf8'))
};
As an additional example, here's how you would do that with a Promise:
// using Node 8's new promisify for our example
const readFileAsync = require('util').promisify(fs.readFile)
const root = {
experiment: () => readFileAsync('./data/experimentExample.json', {encoding: 'utf8'})
.then(data => JSON.parse(data))
};
// Or with async/await:
const root = {
experiment: async () => JSON.parse(await readFileAsync('./data/experimentExample.json', {encoding: 'utf8'}))
};
Of course there's no need to promisify readFile since you already have an async method available, but this gives you an idea of how to work with Promises, which GraphQL is happy to work with.
I would like to retrieve all data from Redis (database '10') into a JSON variable. But I'm a bit confused with asynchronous call... I've tried this:
redis = require('redis');
client = redis.createClient();
client.send_command('select', [10], redis.print);
var r = {};
client.keys('*', function (err, keys) {
keys.forEach(function(c){
client.get(c, function(err, v){
r[c] = v;
});
});
});
console.log(JSON.stringify(r));
client.quit();
But my 'r' JSON variable is empty... How can I do it using callback methods, or synchronous code?
Thanks.
I would try using async module https://github.com/caolan/async to make it async.
redis = require('redis');
client = redis.createClient();
client.send_command('select', [10], redis.print);
var r = {};
client.keys('*', function(err, keys) {
async.each(keys, function(key, callback) {
client.get(key, function(err, value) {
r[key] = value;
callback(err);
});
}, function() {
// when callback is finished
console.log(JSON.stringify(r));
client.quit();
});
});
You can also make it synchronous, using fibrous module https://github.com/goodeggs/fibrous
Synchronous code is dangerous though!