Could you please help with something?
I’m trying to do the following…
import {chosenIpAddress} from './socketEvents.js';
const socket = socketClient(`http:// ${chosenIpAddress} :8081`);
…but no matter what I try, it simply ignores my expression and sees it as http://:8081. I’ve tried with plus signs, commas, backticks, quotation marks, shouting, and threatening it, but to no avail.
I can log out the IP address, so I know it’s populated, but as part of the string it just gets ignored and it’s driving me crazy!
Thanks in advance xxx
P.S... I've seen some similar questions, but these do not help with mine, hence the new question.
Update: As requested, this is my export...
let chosenIpAddress = "";
function chosenTank(tank) {
socket.emit('chosen tank', tank);
console.log('Tank', tank);
chosenIpAddress = tank.IpAddress;
}
export {
chosenIpAddress,
};
You need to export a function that returns the IP address when called.
The file importing the chosenIpAddress has the original value (empty string), but it will never be updated even when chosenTake is called. Javascript strings are copied by value, so if you update the original variable, any other references to it will not be updated.
https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0
Example of strings copied by value:
chosenIpAddress = "";
x = chosenIpAddress; // x is ""
chosenIpAddress = "localhost"; // chosenIpAddress is "localhost", x is still ""
// This same issues applies to imports/exports.
So do something like this in your ip address file:
let chosenIpAddress = "";
function chosenTank(tank) {
socket.emit('chosen tank', tank);
console.log('Tank', tank);
chosenIpAddress = tank.IpAddress;
}
function getChosenIpAddress() {
// This can be "" if chosenTank is not called first
return chosenIpAddress;
}
export {
getChosenIpAddress,
};
Also, as pointed out in the comments, you need to call chosenTank before you access the chosenIpAddress, or you're going to get an empty string every time.
Further, you'll also need to build the socket string as a function as well, so that it gets the most up-to-date value from getChosenIpAddress when it's called:
import {getChosenIpAddress} from './socketEvents.js';
function getChosenSocket() {
return socketClient(`http://${getChosenIpAddress()}:8081`);
}
So, for anyone who runs into this problem, I worked it out. The answer given is kind of getting there, but not right, I tried that (and variations of it), but it/they didn't work.
Basically in my case, the IP address was being set when the application started, so the chosenIpAddress would always be an empty string as it's being set before the connections had taken place, no variations of exporting, recalling, or function building would've done the job.
To get around this, I let the initial connection take place with a 'placeholder' socketClient to stop the application from crashing...
let socket = socketClient('http://:8081');
...and then when ready, I called to repopulate the IP address when the component mounted from the frontend...
Called from front end when ready...
componentDidMount() {
frontEndConnected();
}
Add IP address as required...
function frontEndConnected() {
socket = socketClient(`http://${chosenTankIpAddress}:8081`);
}
...which works a charm.
Related
I am looking to extract a URL parameter from the current URL I'm testing with Cypress. I was able to basically get the answer from this SO post, however, my extracted values are not available to me when I use Cypress's .its() command.
The parameters in the url all have periods in them, and I believe this is the cause for my error.
Here is my custom Cypress Command I'm building:
Cypress.Commands.add('getParmsCommand', function(value) {
cy.url().as('url')
cy.then( () => {
cy.log(this.url)
const kvPairArray = this.url.toString().split('?')[1].toString().split('&')
const paramObj = {}
kvPairArray.forEach(param => {
cy.log(param)
//default 'value' to 0 if it doesn't exist
const [ key, value="0" ] = param.split('=')
paramObj[key] = value
})
//forcefully adding a debug element to the key value store for testing
paramObj['beverage'] = 'soda'
cy.wrap(paramObj)
.its('timeline.ws') //doesn't work
// .its(`${Cypress.$.escapeSelector('timeline.ws')}`) doesn't work
// .its('timeline\.ws') doesn't work
// .its('"timeline.ws"') doesn't work
// .its('beverage') this DOES work!
.then(parmVal => {
cy.log(parmVal)
})
Here is the relevant part of the URL that I'm trying to extract from:
timeline.ws=3600000&timeline.to&timeline.fm&timeline.ar=false
You can see from the error that Cypress is only looking for the id timeline, NOT timeline.ws; it completely ignores everything after the period, and thus, never finds my parameter.
I saw there was a similar error with Cypress's .get() function back in 2018.
I am new to both javascript and Cypress, so I hope it's just a weird easy thing I'm overlooking. Any advice or educated guesses are greatly welcome at this point!
Thank you.
.its() is just a shorthand for property extraction. Since it fails with the period, you could instead use bracket notation in a .then().
cy.wrap(paramObj)
.then(paramObj => paramObj['timeline.ws'])
or just
cy.wrap(paramObj['timeline.ws'])
Playing around with the URL constructor
const urlString = 'http://example.com?timeline.ws=3600000&timeline.to&timeline.fm&timeline.ar=false'
const url = new URL(urlString)
cy.wrap(url.searchParams.get('timeline.ws'))
.should('eq', '3600000')
cy.wrap(url.searchParams.get('timeline.to'))
.should('be.empty')
cy.wrap(url.searchParams.get('timeline.ar'))
.should('eq', 'false')
So, I'm familiar with the general gist of JavaScript's features regarding objects. They're refcounted and if they go to zero, they die. Additionally, apple = banana where both are objects doesn't copy banana to apple but makes apple a reference to banana.
That being said, some of my code has something like this:
// imagine ws require() and setup here...
var RateLimit = require("ws-rate-limit")('10s', 80);
SickWebsocketServer.on("connection", function(mysocket, req){
// blahblahblah...
RateLimit(mysocket); // See below...
mysocket.on("limited", function(){console.log("someone was limited!"});
mysocket.on("message", function(data){
if(JSON.parse(msg).MyFlagToMessageASpecificWebsocketClient){ // obvs dont do this lol
findme = MyArr.find(guy=>guy.Socket==mysocket);
if(findme) console.log("TRIGGER PLS :)"); // GOAL
else console.log("DON'T TRIGGER"); // SOMETHING WENT WRONG
}
});
MyArr.push({MyName:"my SICK object", MyNumber:MyArr.length, Socket:mysocket})
}
The library used for rate limiting is called ws-rate-limit and I have pasted a shortened (non-code removed) version down below (since it's tiny). Imagine it to be in a package called ws-rate-limit (because it is :D).
const duration = require('css-duration')
module.exports = rateLimit
function rateLimit (rate, max) {
const clients = []
// Create an interval that resets message counts
setInterval(() => {
let i = clients.length
while (i--) clients[i].messageCount = 0
}, duration(rate))
// Apply limiting to client:
return function limit (client) {
client.messageCount = 0
client.on('newListener', function (name, listener) {
if (name !== 'message' || listener._rated) return
// Rate limiting wrapper over listener:
function ratedListener (data, flags) {
if (client.messageCount++ < max) listener(data, flags)
else client.emit('limited', data, flags)
}
ratedListener._rated = true
client.on('message', ratedListener)
// Unset user's listener:
process.nextTick(() => client.removeListener('message', listener))
})
// Push on clients array, and add handler to remove from array:
clients.push(client)
client.on('close', () => clients.splice(clients.indexOf(client), 1))
}
}
My issue is that, when I do use the RateLimit function, the "DON'T TRIGGER" code triggers. If I literally remove that one single line (RateLimit(mysocket)) it goes into "TRIGGER PLS :)".
The above is obviously logically simplified from my actual application but I think you get the gist. Apologies for any misspellings that may lead to undefineds or stuff like that; I promise you my code works if not for the RateLimit(mysocket) line.
When I add console.logs into the find function to log both the guy.Socket object and the mysocket object, with the RateLimit(mysocket) line, the mysocket object's .toString() returns [object global] rather than [object Object]. I know that this is some complicated JavaScript object scoping problem, but I have no clue where to start in terms of investigating it.
Thank you! :)
I'll take a random shot in the dark based on intuition. My best guess is that your issue is with the guy.Socket==mysocket line. Comparing objects that way will only check if they both point to the same heap memory location, even if it's two different stack variables. In your example I can only assume that the RateLimit(mysocket) line is somehow creating a new heap location for that stack variable (creating a new object from it) and because of that your == comparison is then no longer equal (even if they have the exact same values) because they're pointing to different locations.
Try using: JSON.stringify(guy.socket) === JSON.stringify(mysocket).
I have an android application I developed, that allows the sign up of users. I wrote a firebase cloud function that triggers when a User is created, to generate a 5-digit random integer value for the user who just signed up and it stores the generated code in firebase real time database in the following structure.
MainProject
|
|-Codes
|-UniqueUID_1
|-code:72834
|-UniqueUID_2
|-code:23784
The function that I deployed in order to make sure that the code generation is in the backend, is as seen below. There is a value "checker" which is initialised as 0. I use this value to determine when to exit the while loop. Basically I want the function to generate a 5-digit random value, then check the real time database if that generated value exists in all entries under "Codes", then if it does not exist, append it to the Codes under the relevant UID. If it exists, checker remains zero and the loop continues.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var checker = 0;
exports.createUserCode = functions.auth.user().onCreate(event => {
while (checker == 0){
var newRand = getUserCode(89999,10000);
var userObject = {
uCode : newRand
};
//run a db query to strategically check value generated
return admin.database().ref("Codes/").orderByChild("uCode").equalTo(newRand).once("value",snapshot => {
if (!snapshot.exists()){
checker = 1;
//add uCode into respective uid slot under Codes
console.log(""+newRand+" : "+event.uid);
return admin.database().ref('Codes/' + event.uid).set(userObject);
}else{
checker = 0;
console.log("uCode "+newRand+" exists");
console.log("uCode generation failed for: "+event.uid);
}
});
}
});
function getUserCode(size, add){
return Math.floor(Math.random()*size+add);
}
I tested it and it worked fine. I thought the problem was solved. However, on the 7th to 11th trial, it gave me a Function returned undefined, expected Promise or value error. I tried it again after a while, and it generated the code fine. Some one else tested it and it brought the same error.
How can I fix this issue to ensure it always works? Thanks in advance.
It's really not clear to me what this function is supposed to do, and the top-level while loop doesn't make sense to me. However, I can see there are a few things wrong with what this code is doing.
First of all, it's depending on the global state checker too heavily. This value will not be the consistent for all function invocations, because they all won't be running on the same server instance. Each running server instance will see a different value of checker. Please watch this video series for more information about how Cloud Functions runs code.
Second of all, when checker has a value of 1 when the function starts, the function will do exactly what the error message says - it will return undefined. It should be pretty easy to see how this happens by reading the code.
To fix this, I suggest first coming up with a clear description of what this function is supposed to do when invoked. Also, I would strongly suggest eliminating dependency on global variables, unless you are absolutely certain you understand what you're doing and the effect they have.
I had the same problem a while ago. ESLint won't allow the function to complete because it evaluates whether every part of your code returns a promise.
From what i can see the first part of the if does return something. Try returning a boolean in the else block.
if (!snapshot.exists()){
checker = 1;
//add uCode into respective uid slot under Codes
console.log(""+newRand+" : "+event.uid);
return admin.database().ref('Codes/' + event.uid).set(userObject);
}else{
checker = 0;
console.log("uCode "+newRand+" exists");
console.log("uCode generation failed for: "+event.uid);
return false;
}
When I am actually entering the XXXX YYYY, then I am getting the players json code in my html page (around 150 values).
But when I am trying to use a function on the players list it somewhy does not contain all the 150 values and the try throws me into the catch error part, where I can see that players json has only 100 players inside there.
Any idea what could be the problem?
if(yourID === "XXXX" && targetID === "YYYY"){
return players;
}
try{
if(isUserAlive(yourID)){
if(targetID === ""){
return userTargetInfo(yourID);
}
var checkForMatch = getUserTarget(yourID);
if(checkForMatch === targetID){
killTarget(targetID);
getUser(yourID).targetID = getTargetTarget(targetID);
addScore(yourID);
return userTargetInfo(yourID);
//return getTargetTargetStats(targetID);
}else{
return "INVALID";
}
}else{
return "DEAD"
}
}catch(err){
console.log("Error",console.log(players))
return "INVALID"
}
Edit: Since I had no time, I created 2 websites and divided the database into 2 different databases, so it would work under 100 people on each. Did not have time to fix the error at this point. So I won't be choosing the solution to that since I won't be trying that any time soon.
Thank you for all your help!
Check the link api that you are using , it might have pagination integrated with it . in that case i will return certain number of object 1st and then you can re-request to get next batch . Most likely they might have a option to change the no of object returned (sometimes with max value)
I'm pretty sure body is returned as a string. Try changing it to an object so you can work with it easier.
Change:
players = body;
to:
players = JSON.parse(body);
I'm not sure the rest of your code, but you may want to add var on your players variable declaration because this looks like the first time you are setting it.
Research: namespace collisions
If you are still having issues, edit your question to include the response you are getting from console.log(JSON.parse(body));. You will be able to get more helpful answers. Personally, I am curious to see the keys such as:
{ query:
{ count: 1,
created: '2017-04-23T22:03:31Z',
lang: 'en-US',
results: { channel: [Object] } } }
If it's paginated, you should see some kind of cursor key in there, or prev and next along with some kind of totalCount.
Hope this helps.
So I've been having this annoying bug for quite some time and I've been hesitant to post here since it's not something you can fix unless you understand the entire code, but this is a really odd error that I'm not able to wrap my head around. I'll try to explain what I'm doing to the best of my ability. I just need to brainstorm and maybe think of possible reasons as to why this is happening. Any help would be really really appreciated! So, here goes.
I have a javascript call that's being made every 2 seconds. The javascript function makes an ajax call which sends a constantly changing value (a video's seek time for example) as so:
function startCron()
{
window.setInterval(function()
{
//Get all the variables, etc. etc.
$.ajax({
type: 'GET',
url: 'updateDetails',
data:
{
'seekTime': upSeekTime
},
success: function(updates)
{
alert(updates);
}
});
}
}, 2000);
}
Now this function works fine! It get's called every 2 seconds, it sends the correct values and it returns back and executes the success function.
Now, the function that my 'updateDetails' URL is calling a function which basically has a series of file operations. It involves opening one file, storing, opening a few other files, finally opening one last file, storing in it and returning back what it just stored. I know, that sounds pretty confusing and some might think it's inefficient, but hang in with me here.
//First file get and put process
$updatedSeekTime = round(Input::get('seekTime'));
$currentDetails = Storage::get("fileone");
list($fileID, $fileStatus, $fileSeekTime) = explode(",", $currentDetails, 3);
$storeMe = array(
"user_id" => $user_id,
"status" => $fileStatus,
"seek_time" => $updatedSeekTime
);
$storeMe = implode(",", $storeMe);
Storage::disk('local')->put($user_id, $storeMe);
//Now for the second file retrieving process
for($i=1;$i<=2;$i++) //Yes, 1 and 2 are file names.
{
$currentDetails = Storage::get($i);
list($fileID, $fileStatus, $fileSeekTime) = explode(",", $currentDetails, 3);
$allSeekKebabs[] = $fileSeekTime;
}
//Now I find all the minimum value from my array
$minSeekVal = min($allSeekKebabs);
//And the final file put process
$storeMe = array(
"user_id" => $user_id,
"status" => $fileStatus,
"seek_time" => $minSeekVal
);
$storeMe = implode(",", $storeMe);
//return $storeMe; //OKAY ATTENTION POINT 1
Storage::disk('local')->put($user_id, $storeMe); //PROBLEM POINT
//return $storeMe; //OKAY ATTENTION POINT 2
Now. If you've made it to this point, a cookie to you because I didn't think most people would read past my code. Ok, so now, here's the really really weird part. Attention point 1 gives me all the correct things. BUT, if I return the SAME variable right after that storage line, like in Attention point 2, the file just stores 0 as the last variable (seek_time according to the last storeMe array). Every other variable in that array comes out right. And the value of seek_time in storeMe is correct UNTIL that damn storage line. After that, the last variable becomes 0. So what it looks like to me is that the storage line is CHANGING my variable! Sounds crazy, right? I've been cracking my head on this for so long.
I have checked EVERY possible line before that problem point and everything is ayy-okay. But that damn line messes everything up and I just can't figure out why. My routes file is fine too!
Any help would be VERY appreciated. You can see how frustrated this thing's gotten me. All I'm asking for is, is there something I'm missing technically. I know that it's near impossible to get a direct answer in this situation, but just any thought, no matter how farfetched, do let me know!
Thanks a lot guys :D
Is $user_id a path that exists on your server ? because it should be:
https://laravel.com/api/5.1/Illuminate/Contracts/Filesystem/Filesystem.html#method_put
bool put( string $path, string|resource $contents, string $visibility = null)
Write the contents of a file.
Parameters
string $path
string|resource $contents
string $visibility
Return Value
bool