Reputation: 25
I'm new to node js. Logically, await should wait for the function to complete and then next line of code should run, but in my function, it doesn't wait for process (2) to finish even after using await. What am I missing?
const getDefaultTemplates = async (token) => {
const emailertoken = process.env.EMAILER_AUTH_TOKEN;
const key = 'defaultTemplates';
// This should run first
console.log('hi');
let defaultTemplatesVar = '';
let fromCache = 0;
// This should run second. Need response from redisClient to return parent function
const defaultTemplates = await redisClient.get(key, (err, data) => {
if (err) {
console.log(err);
}
// If data is found in cache
if (data != null) {
console.log('from cache');
defaultTemplatesVar = JSON.parse(data);
fromCache = 1;
console.log('defaultTemplatesVar1 = ', defaultTemplatesVar);
}
return defaultTemplatesVar;
});
console.log('defaultTemplatesVar2 = ', defaultTemplatesVar);
console.log('fromCache = ', fromCache);
if (fromCache === 0) {
// If data is not found in cache, call api
// console.log('from api');
try {
const response = await axios.get(`${process.env.EMAILER_API_URL}/get-system-templates`, {
headers: {
Authorization: `bearer ${emailertoken}`,
},
});
console.log('from data');
redisClient.setex(key, 3600, JSON.stringify(response.data._embedded.get_system_templates));
defaultTemplatesVar = response.data._embedded.get_system_templates;
console.log('defaultTemplatesVar3 = ', defaultTemplatesVar);
} catch (error) {
console.error(error);
}
}
// This should run at last, to return value to parent function getDefaultTemplates()
console.log('bye');
console.log('defaultTemplatesVar4 = ', defaultTemplatesVar);
return defaultTemplates;
};
OUTPUT ->
hi
defaultTemplatesVar2 =
fromCache = 0
from cache
defaultTemplatesVar1 = [ { name: 'versafix-1', description: 'The versatile template' },
{ name: 'givecentral', description: 'The Givecentral Template' } ]
from data
defaultTemplatesVar3 = [ { name: 'versafix-1', description: 'The versatile template' },
{ name: 'givecentral', description: 'The Givecentral Template' } ]
bye
defaultTemplatesVar4 = [ { name: 'versafix-1', description: 'The versatile template' },
{ name: 'givecentral', description: 'The Givecentral Template' } ]
Output should be in series of 1,2,3,4.
Upvotes: 1
Views: 1242
Reputation: 25
My issue was solved from Allen's Answer.
Only thing I changed in Allen's suggestion was
const data = await redisGet(key);
Instead of
const data = await redisClient.get(key);
because the later one returned 'true' instead of actual values.
const redisGet = (key) => new Promise((resolve, reject) => {
redisClient.get(key, (err, data) => {
if (err) return reject(err);
return resolve(data);
});
});
// Api,Auth Done
const getDefaultTemplates = async (token) => {
const emailertoken = process.env.EMAILER_AUTH_TOKEN;
const key = 'defaultTemplates';
// This should run first
console.log('hi');
let defaultTemplatesVar = '';
let fromCache = 0;
// This should run second. Need response from redisClient to return parent function
try {
const data = await redisGet(key);
if (data != null) {
console.log('from cache');
defaultTemplatesVar = JSON.parse(data);
fromCache = 1;
console.log('defaultTemplatesVar1 = ', defaultTemplatesVar);
}
const defaultTemplates = defaultTemplatesVar;
} catch (err) {
console.error(err);
}
console.log('defaultTemplatesVar2 = ', defaultTemplatesVar);
console.log('fromCache = ', fromCache);
if (fromCache === 0) {
// If data is not found in cache, call api
// console.log('from api');
try {
const response = await axios.get(`${process.env.EMAILER_API_URL}/get-system-templates`, {
headers: {
Authorization: `bearer ${emailertoken}`,
},
});
console.log('from data');
redisClient.setex(key, 3600, JSON.stringify(response.data._embedded.get_system_templates));
defaultTemplatesVar = response.data._embedded.get_system_templates;
console.log('defaultTemplatesVar3 = ', defaultTemplatesVar);
} catch (error) {
console.error(error);
}
}
// This should run at last, to return value to parent function getDefaultTemplates()
console.log('bye');
console.log('defaultTemplatesVar4 = ', defaultTemplatesVar);
return defaultTemplatesVar;
};
OUTPUT 1 (When data comes from the API)
hi
defaultTemplatesVar2 =
fromCache = 0
from data
defaultTemplatesVar3 = [ { name: 'versafix-1', description: 'The versatile template' },
{ name: 'givecentral', description: 'The Givecentral Template' } ]
bye
defaultTemplatesVar4 = [ { name: 'versafix-1', description: 'The versatile template' },
{ name: 'givecentral', description: 'The Givecentral Template' } ]
OUTPUT 2 (When Data comes from Cache)
hi
from cache
defaultTemplatesVar1 = [ { name: 'versafix-1', description: 'The versatile template' },
{ name: 'givecentral', description: 'The Givecentral Template' } ]
defaultTemplatesVar2 = [ { name: 'versafix-1', description: 'The versatile template' },
{ name: 'givecentral', description: 'The Givecentral Template' } ]
fromCache = 1
bye
defaultTemplatesVar4 = [ { name: 'versafix-1', description: 'The versatile template' },
{ name: 'givecentral', description: 'The Givecentral Template' } ]
Upvotes: 0
Reputation: 1433
Callback function can not be await
,
To turn callback fn to Promise fn, check out https://www.npmjs.com/package/redis#promises .
If you are using other packages, you actually can turn callback to promise by
const redisGet = (key) => new Promise((resolve, reject) => {
redisClient.get(key, (err, data) => {
if (err) return reject(err);
return resolve(data);
});
});
// So you can do
const data = await redisGet(key);
// or
redisGet(key).then((data) => { ... }).catch((err) => { ... });
so what you should do
try {
...
const data = await redisClient.get(key);
if (data != null) {
console.log('from cache');
defaultTemplatesVar = JSON.parse(data);
fromCache = 1;
console.log('defaultTemplatesVar1 = ', defaultTemplatesVar);
}
const defaultTemplates = defaultTemplatesVar;
...
} catch (err) {
console.error(err);
}
Simple tutorial about Callback vs Promise
Upvotes: 1