I'm trying to get a redux function to work, however, it throws me this error:
[TypeError: callback is not a function. (In 'callback(true, result)', 'callback' is undefined)]
The function is like this:
export function searchEvent(categories, privateEvent, eventName,
eventCity, eventHourStart, eventHourFinish, eventDayStart, eventDayFinish, callback) {
return async () => {
try {
const ref = firestore().collection('events');
if (categories.length > 0) {
const promises = [];
const allData = [];
categories.forEach(e => {
let query = ref.where(e.field, '==', e.value);
if (privateEvent) {
query = ref
.where(e.field, '==', e.value)
.where('isPrivateEvent', '==', true);
}
const promise = query.get().then(response => {
const data = response.docs.map(d => d.data());
let result = data;
...
allData.push(...result);
}).catch(error => {
console.log(error);
});
promises.push(promise);
});
console.log(allData);
Promise.all(promises).then(() => {
callback(true, allData);
});
} else {
let query = ref;
if (privateEvent) {
query = ref.where('isPrivateEvent', '==', true);
}
query.get().then(response => {
const data = response.docs.map(d => d.data());
let result = data;
...
console.log(result);
callback(true, result);
}).catch(error => {
console.log(error);
});
}
} catch (e) {
console.log(e);
}
};
}
However, I'm pretty sure that I'm passing a callback to said function, as I'm doing it like so:
dispatchSearchEvent(categories, privateEvent, name, city,
hourstart, hourfinish, daystart, dayfinish, (s, r) => {
...
});
So, why it tells me that 'callback' is not a function when I'm clearly passing a callback to it in order to make it work?
I'm still a newbie when it comes to react-redux stuff, so any help will be appreciated.
Related
I am using the google translate api to translate data from a json file to french locale and then write it back to a file. I am using a recursive function to iterate over the json file since it is deeply nested. However the execution is not waiting till the translation is completed before it writes to the file. I have tried using callback and promise approaches but i couldn't get it right.
Just for it to work as I required an output as an emergency I have set a timout before the write method is called. It work but I would like to learn the appropriate/correct approach to implement this.
const fs = require('fs')
const {Translate} = require('#google-cloud/translate').v2
require('dotenv').config()
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0
const credentials = JSON.parse(process.env.credentials)
const translate = new Translate({
credentials,
projectId: credentials.project_id,
})
let data = {}
// writeJSONTofile should be executed only after readJSONFile execution is completed
//read file
const readJSONFile = () => {
try {
data = JSON.parse(fs.readFileSync('...\\locale\\en.json'))
iterateAndTranslate(data)
setTimeout(() => {
writeJSONToFile()
}, 25000)
} catch (error) {
console.log(error)
}
}
// iterate, translate, reassign
const iterateAndTranslate = async (data) => {
for(key in data) {
if (typeof data[key] === 'object' && data[key] !== null) {
iterateAndTranslate(data[key])
} else{
data[key] = await translateText(data[key], 'fr')
}
}
}
//translate method
const translateText = async (text, targetLanguage) => {
try {
let [response] = await translate.translate(text, targetLanguage)
return response
} catch (error) {
console.log(error)
return 0
}
}
const writeJSONToFile = async () => {
var outputFileName = 'C:\\test\\test.json'
await fs.writeFileSync(outputFileName, JSON.stringify(data,null,4), (err) => {
if(err) {
console.log(err)
} else {
console.log('Done!')
}
})
}
// start from here
readJSONFile()
You have a few issues with your code.
Your functions use a global variable and mutate it instead of getting input and returning output.
timeout will cause unexpected behavior in your case.
you are using var
you have redundant async-await on the writeJSONToFile function
See my view of point about the possible solution.
const fs = require("fs");
const { Translate } = require("#google-cloud/translate").v2;
require("dotenv").config();
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
const credentials = JSON.parse(process.env.credentials);
const translate = new Translate({
credentials,
projectId: credentials.project_id,
});
// writeJSONTofile should be executed only after readJSONFile execution is completed
//read file
const readJSONFile = async () => {
try {
const data = JSON.parse(fs.readFileSync("...\\locale\\en.json"));
return iterateAndTranslate(data);
} catch (error) {
console.log(error);
}
return {};
};
// iterate, translate, reassign
const iterateAndTranslate = async (data) => {
for (let key in data) {
if (typeof data[key] === "object" && data[key] !== null) {
await iterateAndTranslate(data[key]);
} else {
data[key] = await translateText(data[key], "fr");
}
}
return data;
};
//translate method
const translateText = async (text, targetLanguage) => {
try {
let [response] = await translate.translate(text, targetLanguage);
return response;
} catch (error) {
console.log(error);
}
return null;
};
const writeJSONToFile = (data) => {
let outputFileName = "C:\\test\\test.json";
fs.writeFileSync(outputFileName, JSON.stringify(data, null, 4), (err) => {
if (err) {
console.log(err);
} else {
console.log("Done!");
}
});
};
// start from here
const run = async () => {
const data = await readJSONFile();
writeJSONToFile(data);
};
run();
See more:
why not using global varible
why not using var
I am trying to use a callback function in my async code but I am getting the error "callback is not a function". What am I doing wrong? I created the callBack function separately and passed it to the async function as a parameter then called it my react component
function myCallBack() {
setTopicLoaded(true);
}
//async function
export function fetchGroupTopic(groupAdminId, myCallback) {
return async (dispatch) => {
dispatch(getTopic());
try {
const myTopic = [];
if (groupAdminId) {
const response = firestore
.collection("topic")
.where("adminId", "==", groupAdminId);
const data = await response.get();
data.docs.forEach((item) => {
let id = item.id;
let data = item.data();
myTopic.push({ id, ...data });
});
myCallback();
dispatch(setGroupTopic(myTopic));
}
} catch (error) {
console.log(error);
dispatch(getTopicFailure());
}
};
}
// calling it here
React.useEffect(() => {
if (myGroup.length) {
fetchGroupTopic(myGroup[0].adminId,myCallBack);
}
}, [id, submitted, myGroup]);
I am trying to use a callBack function in my async code but I am getting the error "TypeError: callBack is not a function". What am I doing wrong? I created the callBack function separately and passed it to the async function as a parameter then called it my useEffect.
function callBack() {
setTopicLoaded(true);
}
function fetchGroupTopic(groupAdminId, callBack) {
return async (dispatch) => {
dispatch(getTopic());
try {
const myTopic = [];
if (groupAdminId) {
const response = firestore
.collection("topic")
.where("adminId", "==", groupAdminId);
const data = await response.get();
data.docs.forEach((item) => {
let id = item.id;
let data = item.data();
myTopic.push({ id, ...data });
});
callBack(); // the error is coming from this line //
dispatch(setGroupTopic(myTopic));
}
} catch (error) {
console.log(error);
dispatch(getTopicFailure());
}
};
}
React.useEffect(() => {
if (myGroup.length) {
fetchGroupTopic(myGroup[0].adminId, callBack);
}
}, [id, submitted, myGroup]);
I am sure this is something basic that I am missing but it's late and my brain gets like that. So I have this function:
export const createRandomHex = () => {
try {
return crypto.randomBytes(127, (_err, buf) => {
console.log("[create] bearerToken: ", buf.toString("hex"));
const bearerTokenString = buf.toString("hex");
return bearerTokenString;
});
} catch (e) {
return e;
}
};
And I am calling it in another function as such:
export const createBearerToken = () => {
const bearerToken = createRandomHex();
}
For some reason, the value of bearerToken in the createBearerToken is undefined or null. Can anyone help me with this?
randomBytes is asynchronous and takes a callback. You could return a promise in your function:
export const createRandomHex = async () => {
return new Promise((resolve, reject) => {
try {
return crypto.randomBytes(127, (_err, buf) => {
console.log("[create] bearerToken: ", buf.toString("hex"));
const bearerTokenString = buf.toString("hex");
resolve(bearerTokenString);
});
} catch (e) {
reject(e);
}
});
};
I have a function that looks like following
export const checkForAvailableAgent = (topicId, serviceUrl, serviceId) => {
const serviceInfo = new window.adiaLive.ServiceInfo({
topicId: topicId, // set here the topicId which you want listen for
OnError: e => {
// react to error message (optional)
console.log("error: ", e);
},
OnServiceStateChange: e => {
if (e.ConnectedAdvisers > 0) {
// there are advisers online for given topicId
console.log("studio available");
return true;
} else {
console.log("studio not available");
return false;
}
}
});
serviceInfo.connect(serviceUrl, serviceId);
};
however the return statements don't return anything when I use the function in the following manner
useEffect(() => {
const agent = checkForAvailableAgent(
`sales_${i18n.language}`,
"https://linktoserviceurl",
"serviceid"
);
// console.log("studio available is: ", agent);
}, []);
the console.log massages appear but the return statement is undefined.
any help would be appreciated.
You can not return from a callback function, as it is running asynchronously and you are not waiting for it to have a result ready.
You can however make the function itself async by returning a Promise instead of the actual result and wait until the Promise has a result ready (e.g. it is resolved):
export const checkForAvailableAgent = (topicId, serviceUrl, serviceId) => {
return new Promise((resolve, reject) => {
const serviceInfo = new window.adiaLive.ServiceInfo({
topicId: topicId, // set here the topicId which you want listen for
OnError: e => {
// react to error message (optional)
console.log("error: ", e);
reject(); // reject on failure
},
OnServiceStateChange: e => {
if (e.ConnectedAdvisers > 0) {
// there are advisers online for given topicId
console.log("studio available");
resolve(true); // resolve instead of return
} else {
console.log("studio not available");
resolve(false);
}
}
});
serviceInfo.connect(serviceUrl, serviceId);
})
};
useEffect(() => {
checkForAvailableAgent(
`sales_${i18n.language}`,
"https://linktoserviceurl",
"serviceid"
).then((agent) => { // then callback is called when the promise resolved
console.log("studio available is: ", agent);
}).catch(error => { // catch is called when promise got rejected
console.log('An error happened');
});
}, []);
The function servceInfo.OnServiceStateChange is a function into the object (seems to be an event).
I'd suggest declaring a variable on the checkForAvailableAgent like connected and change it's value when the event is called.
Then access it using checkForAvailableAgent.connected.
A version with async/await and try/catch
export const checkForAvailableAgent = (topicId, serviceUrl, serviceId) => {
return new Promise((resolve, reject) => {
const serviceInfo = new window.adiaLive.ServiceInfo({
topicId: topicId,
OnError: reject,
OnServiceStateChange: e => resolve(e.ConnectedAdvisers > 0)
});
serviceInfo.connect(serviceUrl, serviceId);
})
};
useEffect(() => {
(async () => {
try {
const isAvailable = await checkForAvailableAgent(
`sales_${i18n.language}`,
"https://linktoserviceurl",
"serviceid"
);
// console.log("Result", isAvailable)
} catch(e) {
console.error(e)
}
})()
// console.log("studio available is: ", agent);
}, []);
There are 2 possible reasons
you are not returning anything from checkForAvailableAgent.
After returning from the checkForAvailableAgent, it might be asynchronous function. You can use async & await.