Trying to declare variable within useEffect: - javascript

I'm really not sure what I am doing wrong
Please help out...
Is there a better way to access a variable declared within the useEffect?
Thanks
So I have the following code - but I get the error:
[TypeError: "setDevice" is read-only]
const [device, setDevice] = useState( '' );
React.useEffect(() => {
const device_id = async () => {
var DeviceInfo = require('react-native-device-info');
var deviceId = DeviceInfo.getUniqueId();
const filePath = RNFS.DocumentDirectoryPath + deviceId + "_secret.json";
if (await RNFS.exists(filePath)){
RNFS.readFile(filePath, 'utf8')
.then((contents) => {
try{
// setDev = String(contents);
var JSONObject = JSON.parse(contents);
console.log(JSONObject['device_id']);
setDevice = JSONObject['device_id'];
}catch(err){
console.log("Error: ", err);
}
});
console.log("FILE EXISTS: " + filePath);
} else {
function makeid() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < 5; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
var dev_id = makeid() + deviceId;
var id = '{"device_id" : "'+dev_id+'"}';
RNFS.writeFile(filePath, id, 'utf8')
.then((success) => {
console.log('FILE WRITTEN!');
navigation.dispatch(resetReachOutPreferences)
})
.catch((err) => {
console.log(err.message);
});
}
}
device_id();
}, []);
console.log("ID: " + device);
I've tried useState(null)

From the React documentation on the State hook:
What does useState return? It returns a pair of values: the current state and a function that updates it.
So in this case, setDevice is a function that can be used to update the value of device (which will be reflected on subsequent renders). Instead of assigning to it, you should call it with the new value as its argument, e.g.:
setDevice(contents);

Related

Pulling from cryptowatch API

I am trying to pull price data from the API for cryptowatch, when I go to the URL with my API key it works fine, but my program isn't successfully pulling it so I am getting my error of Could not set price feed for cryptowatch:" + cryptowatchMarketId
I'm pretty stuck on where to go from here.
// Set initial prices
const cryptowatchApiKey = process.env.CRYPTOWATCH_API_KEY || MM_CONFIG.cryptowatchApiKey;
const cryptowatchMarkets = await fetch("https://api.cryptowat.ch/markets?apikey=" + cryptowatchApiKey).then(r => r.json());
const cryptowatchMarketPrices = await fetch("https://api.cryptowat.ch/markets/prices?apikey=" + cryptowatchApiKey).then(r => r.json());
for (let i in cryptowatchMarketIds) {
const cryptowatchMarketId = cryptowatchMarketIds[i];
try {
const cryptowatchMarket = cryptowatchMarkets.result.find(row => row.id == cryptowatchMarketId);
const exchange = cryptowatchMarket.exchange;
const pair = cryptowatchMarket.pair;
const key = `market:${exchange}:${pair}`;
PRICE_FEEDS['cryptowatch:'+cryptowatchMarketIds[i]] = cryptowatchMarketPrices.result[key];
} catch (e) {
console.error("Could not set price feed for cryptowatch:" + cryptowatchMarketId);
}
}
const subscriptionMsg = {
"subscribe": {
"subscriptions": []
}
}
for (let i in cryptowatchMarketIds) {
const cryptowatchMarketId = cryptowatchMarketIds[i];
// first get initial price info
subscriptionMsg.subscribe.subscriptions.push({
"streamSubscription": {
"resource": `markets:${cryptowatchMarketId}:book:spread`
}
})
}
let cryptowatch_ws = new WebSocket("wss://stream.cryptowat.ch/connect?apikey=" + cryptowatchApiKey);
cryptowatch_ws.on('open', onopen);
cryptowatch_ws.on('message', onmessage);
cryptowatch_ws.on('close', onclose);
cryptowatch_ws.on('error', console.error);
function onopen() {
cryptowatch_ws.send(JSON.stringify(subscriptionMsg));
}
function onmessage (data) {
const msg = JSON.parse(data);
if (!msg.marketUpdate) return;
const marketId = "cryptowatch:" + msg.marketUpdate.market.marketId;
let ask = msg.marketUpdate.orderBookSpreadUpdate.ask.priceStr;
let bid = msg.marketUpdate.orderBookSpreadUpdate.bid.priceStr;
let price = ask / 2 + bid / 2;
PRICE_FEEDS[marketId] = price;
}
function onclose () {
setTimeout(cryptowatchWsSetup, 5000, cryptowatchMarketIds);
}
}

How to trigger firebase http function in node.js?

I am trying to trigger an another function in Firebase Cloud function with javascript. But i always getting an error of Can't set headers after they are sent. Please take a look at my code below: ................. ................. ............ ................ ................. ............... ....................... .................. ..............
exports.productIndexShuffleOne = functions.https.onRequest(async (req, res) => {
const interval = req.query.interval;
console.log("interval: "+interval);
const productRef = admin.firestore().collection("Products");
const adminRef = admin.firestore().collection("Admin").doc("totalProd").get();
const dateRef = admin.firestore().collection("Admin").doc("totalProd").collection("indexShuffle").doc("productShuffle").get();
return dateRef.then(documentSnapshot => {
const setDate = documentSnapshot.get('date').seconds;
var nextDay = setDate;
console.log("Date: "+nextDay);
const x = setInterval(function() {
clearInterval(x);
return Promise.all([adminRef]).then(result => {
const totalNum = result[0].data().totalNumber;
console.log("totalNum: "+totalNum);
var numberList = [];
var index = 1;
while(index <= totalNum){
numberList.push(index);
index++;
}
var cidx, ridx, tmp;
cidx = numberList.length;
while (cidx !== 0) {
ridx = Math.floor(Math.random() * cidx);
cidx--;
tmp = numberList[cidx];
numberList[cidx] = numberList[ridx];
numberList[ridx] = tmp;
}
console.log(numberList);
var counter = 0;
return productRef.get().then(snapshot => {
snapshot.forEach(doc => {
const prodID = doc.get('productID');
const index = doc.get('index');
var newIndex = numberList[counter];
counter++;
console.log("oldIndex: "+index);
console.log("newIndex: "+newIndex);
productRef.doc(prodID).update({
index: newIndex
}, {merge: true});
});
return res.redirect('https://us-central1-myfunction-123456.cloudfunctions.net/productIndexShuffleTwo?interval='+interval);
})
.catch(err => {
console.log('Error getting documents', err);
});
});
}, interval);
return res.status(203).send(interval);
}).catch(function(err) {
console.error(err);
});
});
This is because you've sent multiple responses while the rule is that you only allowed sending one response. Please try to look at your code and optimize it in such a way that it contains only one response.
I can see you have multiple responses as below:
1 -> return res.redirect('https://us-central1-myfunction-123456.cloudfunctions.net/productIndexShuffleTwo?interval='+interval);
2 -> return res.status(203).send(interval);
I believe that you can have res.redirect and then res.status.send called one after another. When you writing endpoints there rule of a thumb: always send response and only do that once. Refactor your code so there no way you can make those two calls, but only one of them.

I am trying to call a function that includes a promise. Javascript [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I am calling this function called numberOfRedeems(dealId) from another function called setUpData. Note that the numberOfRedeems() function has a promise and returns the "counter".
When I run the same function from the setUpData function it always comes undefined. Please tell me why this is happening. Would be highly appreciated!
I suspect the problem is that there is a promise in the function that im calling.
function getNumberOfRedeems(dealId){
userId = firebase.auth().currentUser.uid;
var counter = 0;
db.collection("redeemedDeals").get()
.then(function(querySnapshot){
querySnapshot.forEach(function(doc) {
var data = doc.data();
var docDealID = data.deal;
console.log(docDealID);
if (dealId == docDealID){
counter = counter + 1;
}
});
}).then(function(){
console.log(counter);
return counter;
})
}
function setUpData(){
$("#uploadingProgress").hide();
var user = firebase.auth().currentUser
var userId = user.uid
var userRef = db.collection('partners').doc(user.uid);
return userRef
.get()
.then(doc => {
if (doc.exists) {
try{
userName = doc.get("name")
$("#partnerName").show().text(userName);
}catch(error) {
console.error("Could not retrieve ", error);}
}
db.collection("partners").doc(userId).collection("dealHistory").get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(dealHistoryDocRef) {
db.collection("deals").doc(dealHistoryDocRef.id).get().then(function(doc){
var dealId = dealHistoryDocRef.id
table.innerHTML += "<td><a id="+doc.get("id")+">"+doc.get("name")+"</a></td><td>" + getNumberOfRedeems(dealId) + "</td><td>"+doc.get("id")+"</td>"
})
});
});
})}
I expect the it to return a number, but its always undefined.
First your func getNumberOfRedeems needs to be a Promise and return a counter from resolve.
function getNumberOfRedeems(dealId){
return new Promise((resolve, reject) => {
userId = firebase.auth().currentUser.uid;
var counter = 0;
db.collection("redeemedDeals").get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
var data = doc.data();
var docDealID = data.deal;
console.log(docDealID);
if (dealId == docDealID){
counter = counter + 1;
}
});
}).then(() => {
console.log(counter);
resolve(counter);
})
})
}
Second, where you calls it, needs to be await getNumberOfRedeems and add async specific word before function declaration, like:
db.collection("deals")
.doc(dealHistoryDocRef.id)
.get()
.then(async doc => {
var dealId = dealHistoryDocRef.id
table.innerHTML += "<td><a id="+doc.get("id")+">"+doc.get("name")+"</a>
</td><td>" + await getNumberOfRedeems(dealId) + "</td><td>"+doc.get("id")+"</td>"
})

how to pass variable in error

Heyo,
I have a following function
async function fnIsOnScreenOnce(img, desc,iCounter,client,repeatDelay=0) {
await timeout(repeatDelay);
let screenshot= await client.screenshot()
let buf = new Buffer(screenshot.value, 'base64');
let img1 = cv.imdecode(buf)
let result = img1.matchTemplate(img, 5).minMaxLoc();
result.screenshot=img1;
if (result.maxVal <= 0.65) {
// Fail
const msg = "Can't see object yet";
throw new Error(result);
}
// All good
console.log("result:"+result)
logger.info("Found image on screen: "+desc);
return result;
}
Call of the function
function fnIsOnScreen(img,client, repeats = 5, desc, wait = 2000,repeatDelay) {
logger.info("Looking for image on screen:" +desc +" with " + repeats + " repeats ");
let iCounter = 0;
let init = ()=> timeout(wait).then((asd)=>{
const attempt = () => fnIsOnScreenOnce(img, desc, iCounter,client,repeatDelay).then((data=>{
let imagepath=fnMarkOnImage(data.screenshot,img,data,outputDir)
let description={};
description.action="Is image on screen ?";
description.desc=desc;
description.repeats=repeats;
description.wait=wait;
description.img=imagepath;
description.message="is this correct element ? if is then it was found correctly";
fnPushToOutputArray(description)
return data;
})).catch(err => {
console.log(JSON.stringify(err));
console.log(err);
console.log(err.result);
iCounter++;
if (iCounter === repeats) {
// Failed, out of retries
logger.info("Object not found : " + desc);
return Promise.reject("Object not found : " + desc);
}
// Retry after waiting
return attempt();
});
return attempt();
})
return init();
}
result object contains some date.
On error result contains {} object with no values in it. I would need to get all the values. So how can i pass result object through throw new error to retrieve it in catch ?
One way to return extra data with error is to extend Error class and add them your self
class MyError extends Error {
constructor(message, errorExtraParams) {
super(message);
this._errorExtraParams = errorExtraParams;
}
get errorExtraParams() {
return this._errorExtraParams;
}
}
throw new MyError("Error!!!", {})
//or
let mError = new MyError("Error!!!", {})
console.log(mError.errorExtraParams)
But I suggest you don't use throw Error, because I don't like to throw Errors for insignificant reasons. What I mean is that in your case there is no reason to throw error cause there is no error and no reason to create an error just to tell you code "Hey I didnt find the image" instead just return false.
async function fnIsOnScreenOnce(img, desc, iCounter, client, repeatDelay = 0) {
await timeout(repeatDelay);
let screenshot = await client.screenshot()
let buf = new Buffer(screenshot.value, 'base64');
let img1 = cv.imdecode(buf)
let result = img1.matchTemplate(img, 5).minMaxLoc();
result.screenshot = img1;
if (result.maxVal <= 0.65) {
const msg = "Can't see object yet";
return false;
}
// All good
console.log("result:" + result)
logger.info("Found image on screen: " + desc);
return result;
}
function fnIsOnScreen(img, client, repeats = 5, desc, wait = 2000, repeatDelay) {
logger.info("Looking for image on screen:" + desc + " with " + repeats + " repeats ");
let iCounter = 0;
let init = () => timeout(wait).then((asd) => {
let found = false;
do {
let found = await fnIsOnScreenOnce(img, desc, iCounter, client, repeatDelay)
} while (found !== false && iCounter++ < 10)
let imagepath = fnMarkOnImage(found.screenshot, img, found, outputDir)
let description = {};
description.action = "Is image on screen ?";
description.desc = desc;
description.repeats = repeats;
description.wait = wait;
description.img = imagepath;
description.message = "is this correct element ? if is then it was found correctly";
fnPushToOutputArray(description)
return found;
})
return init();
}
You should pass a String to the Error Object, so if you want to exchange an object you could use JSON.stringify() like this:
try {
throw new Error(JSON.stringify({result:"Hello, World"}));
}
catch(error) {
console.log(JSON.parse(error.message))
}
As you can see, this is how you would send data from a try to a catch through throwing errors. You can ofc make the second part in the catch way shorter:
error = JSON.parse(error.message);
You can try an approach like this
try {
const err = new Error("My Error Occurred");
err.extra ='Extra details';
throw err;
}
catch (error) {
console.log(error.extra)
}
As Error itself is an Object ,We can make use of this to pass extra variables of our choice

how do i add variables to url requests in javascript, more specifically, expo and react native

i am currently making this request via fetch in expo
const response = await fetch(`https://graph.facebook.com/v2.9/{{{i need to enter the id here}}}/friends?access_token=${token}`);
I have user.id but I am not sure how to call id in the string
here is the entire function, everything works except the {id} in the string
login = async () => {
const ADD_ID = '<APP ID>'
const options = {
permissions: ['public_profile', 'email', 'user_friends'],
}
const {type, token} = await Expo.Facebook.logInWithReadPermissionsAsync(ADD_ID, options)
if (type === 'success') {
const response = await fetch(`https://graph.facebook.com/me?access_token=${token}`)
const user = (await response.json());
const id = user.id;
console.log(user);
console.log(id);
this.authenticate(token)
}
try {
const response = await fetch(`https://graph.facebook.com/v2.9/{id}/friends?access_token=${token}`);
console.log(await response.json())
} catch(error) {
console.error(error);
}
}
Let define your own format String function and move your try catch inside if expression
String.format = function() {
// The string containing the format items (e.g. "{0}")
// will and always has to be the first argument.
var theString = arguments[0];
// start with the second argument (i = 1)
for (var i = 1; i < arguments.length; i++) {
// "gm" = RegEx options for Global search (more than one instance)
// and for Multiline search
var regEx = new RegExp("\\{" + (i - 1) + "\\}", "gm");
theString = theString.replace(regEx, arguments[i]);
}
return theString;
}
console.log(String.format('https://graph.facebook.com/v2.9/{0}/friends?access_token=${1}', id, token))

Categories