Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Roadie
Jun 30, 2013

Dominoes posted:

What method do you recommend for causing a long calculation to not block the main thread? I'm attempting to use async, but am likely doing it wrong. Case: Have some long validations that once complete, trigger a Redux update. What currently happens is the app hangs until they're done. Is there a way I can make the GUI run smoothly while the calc is being performed, and update the Redux state once complete? From what I've read, it appears that prepending the long funcs with 'async' should accomplish this. Don't need to return anything, just let Redux update the state once complete.

Use a promise-handling lib for Redux like redux-thunk (also, make sure you know the equivalencies between async/await and promises). Default Redux is designed for sync operations only, but it's easy for various libs to add async handling via middleware. If the long calculations are really CPU-heavy, you could also put them into a webworker using a lib like threads.js.

Roadie fucked around with this message at 02:17 on Jan 7, 2019

Adbot
ADBOT LOVES YOU

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Nolgthorn posted:

Not to tell you how to do it but I'd just compile separate js files as needed, then use the `async` html tag. Bingo bongo and it's done. The only thing typescript's compiler is bizarrely still missing is iife, so I use something lightweight like buble when I need it if I'm using typescript.

Webpack is like trying to land a rocket on mars, when all you really want is a little fin that's on the rocket. It has like 8 billion dependencies, it's a bloody mess.
That sounds like the "just do it myself with loving makefiles" option that I considered a while back. But I don't want to end up with as many js files as I have ts files - one of the things webpack does nicely is it takes my 20-or-whatever typescript files and it turns them into three or four somewhat-minified js files (and map files!) in the most appropriate configuration for dynamic loading.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Dominoes posted:

What method do you recommend for causing a long calculation to not block the main thread?
A method I used that's easy and cheap is something like this:
code:
function moment() {
	return new Promise((f) => {
		setTimeout(() => f(true), 0);
	});
}
async function yourLongFunction() {
	// [at some not-too-common occasion]
	await moment();
}
If you await moment() too often it will take thousands of times longer to run your function though. You can either call it less often, or put something in there so it returns Promise.resolve() if it was called recently, and the setTimeout promise otherwise - even then you still don't want to call it super often, but like 10000 times a second with that version is fine.

Dominoes
Sep 20, 2007

roomforthetuna posted:

A method I used that's easy and cheap is something like this:
code:
function moment() {
	return new Promise((f) => {
		setTimeout(() => f(true), 0);
	});
}
async function yourLongFunction() {
	// [at some not-too-common occasion]
	await moment();
}
If you await moment() too often it will take thousands of times longer to run your function though. You can either call it less often, or put something in there so it returns Promise.resolve() if it was called recently, and the setTimeout promise otherwise - even then you still don't want to call it super often, but like 10000 times a second with that version is fine.
This appears to work as a quick in-place fix! Much easier than I'd assumed. Of note, the call to await moment_() must be at the top of the func; eg the slow code below.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Dominoes posted:

This appears to work as a quick in-place fix! Much easier than I'd assumed. Of note, the call to await moment_() must be at the top of the func; eg the slow code below.
You have to call await moment() repeatedly from the slow function to have it work. Waiting for a setTimeout of duration zero to resolve essentially means "yield for one UI cycle now". There is no way to actually multithread javascript other than introducing webworkers, which are relatively high effort.

Dominoes
Sep 20, 2007

I don't understand this, (Need to dig into the MDN docs) but placing your code at a key point fixed the problem almost entirely.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense

Dominoes posted:

What method do you recommend for causing a long calculation to not block the main thread? I'm attempting to use async, but am likely doing it wrong. Case: Have some long validations that once complete, trigger a Redux update. What currently happens is the app hangs until they're done. Is there a way I can make the GUI run smoothly while the calc is being performed, and update the Redux state once complete? From what I've read, it appears that prepending the long funcs with 'async' should accomplish this. Don't need to return anything, just let Redux update the state once complete.

Javascript is still single threaded. Although you may async appropriately, if it's CPU heavy it will block the thread at whatever point that the stack decides to process it. What you may be looking for is web workers.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Nolgthorn posted:

Javascript is still single threaded. Although you may async appropriately, if it's CPU heavy it will block the thread at whatever point that the stack decides to process it. What you may be looking for is web workers.

This is an excellent point. It's often confusing to folks because the frequent use for async is for network calls (fetch, etc.), which are offloaded to the browser, so it can *appear* like you passed off the stuff to another thread, but you didn't, and the stuff that you call on the success / failure of said network call is tacked on to the event loop.

So:

code:
async function doAThing() {
    fetch(url) // handed off to browser, so no blocking
    .then(response => someIntenseShit()) // gets put on event loop, can / will block
}

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop is already kind of convoluted but then there are also microtasks which, well, have fun!

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Munkeymon posted:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop is already kind of convoluted but then there are also microtasks which, well, have fun!

This: https://www.youtube.com/watch?v=8aGhZQkoFbQ is in my opinion, the bestest thing for understanding the event loop.

Dominoes
Sep 20, 2007

Thank you for the detailed info on threading/async and events loops!

roomforthetuna posted:

You have to call await moment() repeatedly from the slow function to have it work. Waiting for a setTimeout of duration zero to resolve essentially means "yield for one UI cycle now". There is no way to actually multithread javascript other than introducing webworkers, which are relatively high effort.
This solved my understanding-issue. In my case, your soln worked well: My problem was the UI would hang when the user manipulates certain items, which triggered detailed validations, each taking a second or two. This made it feel clumsy and unresponsive. Allowing the UI to run briefly after the user action allowed the UI to update almost immediately, while the validation errors updated at their leisure.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Lumpy posted:

This: https://www.youtube.com/watch?v=8aGhZQkoFbQ is in my opinion, the bestest thing for understanding the event loop.

Oh yeah I think I remember someone linking to Loupe that year.

https://www.youtube.com/watch?v=SrNQS8J67zc
also has good information but that lady needs to polish up her delivery.

MrMoo
Sep 14, 2000

roomforthetuna posted:

Relatedly, has anyone here done anything with WebRTC? That's nearly as much of a clusterfuck to get going as webpack+typescript+npm. I got that working too, finally, and all it requires is like 14 messages through two server connections in order to establish one peer-to-peer connection.

Sounds like you are holding it wrong. The spec has changed a lot which is the most annoying. I have a video wall setup to render a 16K video with it.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

MrMoo posted:

Sounds like you are holding it wrong. The spec has changed a lot which is the most annoying. I have a video wall setup to render a 16K video with it.
As far as I can tell you need:
1. one peer sends an RTCSessionDescriptionInit to the other via the server.
2. the other peer applies that one and generates a response one, sends that RTCSessionDescriptionInit to the first peer.
3. both peers now start generating IceCandidates, which it seems to be recommended you communicate as soon as they are generated. In my test case, each side generated 6 RTCIceCandidateInit objects, which makes it 14 messages through the server total. I figure you probably could clump all the IceCandidates together into one message each way, since more are generated even if you don't send them, but I'm not sure if that would be better or worse (also not sure if the list is communicated via the callback with some kind of a null-terminator at the end or what, none of the examples were clear on why it's valid for an IceCandidateEvent to have its 'candidate' property unset.)

Raskolnikov2089
Nov 3, 2006

Schizzy to the matic
https://www.youtube.com/watch?v=cCOL7MC4Pl0

My favorite explanation of the event loop.

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop
I have a key-value collection of arrays, and each array is expected to be the same length.

Example test data:

code:
const arrays = { a: Array(10), b: Array(10), c: Array(10) };
What is the most concise way to retrieve that length?

Object.values( arrays )[0].length seems kind of excessive since it has to touch all the stored arrays when i just need one.

playground tough
Oct 29, 2007

Dumb Lowtax posted:

I have a key-value collection of arrays, and each array is expected to be the same length.

Example test data:

code:
const arrays = { a: Array(10), b: Array(10), c: Array(10) };
What is the most concise way to retrieve that length?

Object.values( arrays )[0].length seems kind of excessive since it has to touch all the stored arrays when i just need one.

Do you know the keys?

code:
arrays["key"].length or arrays.key.length
Don't?

code:
let keys = Object.keys(arrays)
arrays[ keys[0] ].length
Not sure if there's js magic to do it any simpler... though js magic sucks so

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop
I love es6 magic tricks, just hoping to discover a new one for this (keys are unknown)

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Dumb Lowtax posted:

I have a key-value collection of arrays, and each array is expected to be the same length.

Example test data:

code:
const arrays = { a: Array(10), b: Array(10), c: Array(10) };
What is the most concise way to retrieve that length?

Object.values( arrays )[0].length seems kind of excessive since it has to touch all the stored arrays when i just need one.
If you're targeting an ES6 target and you're also in control of your key-value collection, you could make the collection as a Map rather than a {} object, which would then allow you to access it as an iterator rather than duplicating the keys into an array, which I believe would allow you to look at just the first element.

But if your data is going to/from JSON or something then you might be just front-loading the extra pass to do that.

SimonChris
Apr 24, 2008

The Baron's daughter is missing, and you are the man to find her. No problem. With your inexhaustible arsenal of hard-boiled similes, there is nothing you can't handle.
Grimey Drawer

roomforthetuna posted:

As far as I can tell you need:
1. one peer sends an RTCSessionDescriptionInit to the other via the server.
2. the other peer applies that one and generates a response one, sends that RTCSessionDescriptionInit to the first peer.
3. both peers now start generating IceCandidates, which it seems to be recommended you communicate as soon as they are generated. In my test case, each side generated 6 RTCIceCandidateInit objects, which makes it 14 messages through the server total. I figure you probably could clump all the IceCandidates together into one message each way, since more are generated even if you don't send them, but I'm not sure if that would be better or worse (also not sure if the list is communicated via the callback with some kind of a null-terminator at the end or what, none of the examples were clear on why it's valid for an IceCandidateEvent to have its 'candidate' property unset.)

An unset 'candidate' property indicates that ICE candidate gathering has finished. If you want to transmit all the candidates together, you are supposed to wait until you receive a 'null' candidate, indicating that no more candidates are forthcoming.

Also, the reason you are supposed to transmit the candidates right away is that it theoretically allows for your app to start transmitting data as soon as a single candidate has been received, and then upgrade the connection if at better candidate is found later. In practice, I have never had ICE candidate gathering take more than a fraction of a second, so this seems to be of dubious utility.

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop

roomforthetuna posted:

If you're targeting an ES6 target and you're also in control of your key-value collection, you could make the collection as a Map rather than a {} object, which would then allow you to access it as an iterator rather than duplicating the keys into an array, which I believe would allow you to look at just the first element.

But if your data is going to/from JSON or something then you might be just front-loading the extra pass to do that.

Thanks for answering another of my questions! I think I will go with this. I'm targetting es6 and I guess there's no downsides to a small Map stored in everything vs a small {}.

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop
I use SimpleHTTPServer to develop JS locally and just now started trying to use es6 modules. Unfortunately SimpleHTTPServer doesn't know about .mjs files and delivers the wrong mime type for them. Is there a workaround anyone knows that's simple enough to get hundreds of my students to reliably repeat, or should I just wait on introducing modules to our code until a fix comes in (which looks like soon)?

Dominoes
Sep 20, 2007

Dumb Lowtax posted:

I use SimpleHTTPServer to develop JS locally and just now started trying to use es6 modules. Unfortunately SimpleHTTPServer doesn't know about .mjs files and delivers the wrong mime type for them. Is there a workaround anyone knows that's simple enough to get hundreds of my students to reliably repeat, or should I just wait on introducing modules to our code until a fix comes in (which looks like soon)?

Here's a script I use, for the Python3 version and wasm. Edit the handler.extensions section for your mime type:
Python code:
#!/usr/bin/env python3

import http.server
import os
import socketserver
import urllib

PORT = 8000


# Add support for the WASM mime type.
http.server.SimpleHTTPRequestHandler.extensions_map.update({
    '.wasm': 'application/wasm',
})

socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer(("", PORT), handler) as httpd:
    httpd.allow_reuse_address = True
    print("Serving at port", PORT)
    httpd.serve_forever()

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop

Dominoes posted:

Here's a script I use, for the Python3 version and wasm. Edit the handler.extensions section for your mime type:

Sorry, I don't know how to do this. I hope I would just need to paste that into a file somewhere but I'm not confident Windows makes it that easy. Basically assume that I have no experience with Python besides running the Windows installer and then running a batch file I wrote that calls SimpleHTTPServer in the current folder. This is going to be the experience level of many of my students too. Either way, is this going to make my instructions document for them twice as long about how to set up our local JS development? If so I need another way.

Secondly, is this bug maybe already fixed? It looks like they were working on it last week, and the issue is marked as fixed: https://bugs.python.org/issue31715
Can anyone read bug-tracker speak and find out what Python release version this patch can be expected in?

Happy Thread fucked around with this message at 20:17 on Jan 9, 2019

The Fool
Oct 16, 2003


Dumb Lowtax posted:

Sorry, I don't know how to do this. I hope I would just need to paste that into a file somewhere but I'm not confident Windows makes it that easy. Basically assume that I have no experience with Python besides running the Windows installer and then running a batch file I wrote that calls SimpleHTTPServer in the current folder. This is going to be the experience level of many of my students too. Either way, is this going to make my instructions document for them twice as long about how to set up our local JS development? If so I need another way.

Secondly, is this bug maybe already fixed? It looks like they were working on it last week, and the issue is marked as fixed: https://bugs.python.org/issue31715
Can anyone read bug-tracker speak and find out what Python release version this patch can be expected in?

The mimetype addition appears to have been committed 20 days ago, which would put it in the 3.7.2 and 3.6.8 releases.

e: It has also been added to the 2.7 branch, but there hasn't been new release of that branch.

The Fool fucked around with this message at 20:35 on Jan 9, 2019

Dominoes
Sep 20, 2007

Dumb Lowtax posted:

Sorry, I don't know how to do this. I hope I would just need to paste that into a file somewhere but I'm not confident Windows makes it that easy. Basically assume that I have no experience with Python besides running the Windows installer and then running a batch file I wrote that calls SimpleHTTPServer in the current folder. This is going to be the experience level of many of my students too. Either way, is this going to make my instructions document for them twice as long about how to set up our local JS development? If so I need another way.

Secondly, is this bug maybe already fixed? It looks like they were working on it last week, and the issue is marked as fixed: https://bugs.python.org/issue31715
Can anyone read bug-tracker speak and find out what Python release version this patch can be expected in?
-Replace '.wasm': 'application/wasm', in the script I posted with '.mjs':' text/javascript'
-Copy the text from my code block. Paste it into a text editor. Save the file as serve.py to the directory of your project
-Download Python here Python 3. Run the installer.
-Open Powershell in the directory you saved the file. Type python serve.py

Dominoes fucked around with this message at 22:42 on Jan 9, 2019

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop

The Fool posted:

The mimetype addition appears to have been committed 20 days ago, which would put it in the 3.7.2 and 3.6.8 releases.

Oh! That's out now. I'll re-download, thanks! Go progress

edit: The error is gone! Thanks!

Happy Thread fucked around with this message at 23:39 on Jan 9, 2019

geeves
Sep 16, 2004

LifeLynx posted:

I was happy with this script I wrote (maybe not entirely from an efficiency standpoint) until I realized it doesn't work in any iOS browser. It doesn't work in IE11 either, but I don't mind that too much.

Is it possible to tweak this slightly so it works without IntersectionObserver, which is the reason it's not behaving nicely with Safari on iOS?

Others have mentioned the Polyfill for IntersectionObserver

I cleaned up the JS a little bit because I'm bored and trying to purge my brain of docker compose madness

code:
document.addEventListener("DOMContentLoaded", event => {
  const scrollPastTargetNo = document.querySelectorAll(".anim-target");
  const animatedClasses = ["zoomIn", "fadeIn", "fadeInUp", "bounceIn", "slideInLeft"];
  const allClasses = ["animated", ...animatedClasses];
  const observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
      const addClasses = [];
      const cl = entry.target.classList;
      if (entry.isIntersecting) {
        animatedClasses.forEach(ac => {
          if (cl.contains(`anim-target-${ac}`)) {
            addClasses.push(ac);
          }
        });

        if (0 < addClasses.length) {
          // Yes, classList.add will only add animated once, but meh. only add it if needed.
          addClasses.push("animated");
        }
        
        cl.add(...addClasses);
        console.log("Animate target activated");
      } else {
        cl.remove(...allClasses);
        entry.target.style.opacity = 0;
        //observer.unobserve(entry.target);
        console.log("Animate target deactivated");
      }
    });
  });

  // For IE11 - querySelectorAll returns a NodeList which doesn't work with forEach in older browsers
  Array.from(scrollPastTargetNo).forEach(image => {
    observer.observe(image);
  });

});

geeves fucked around with this message at 04:15 on Jan 10, 2019

Siddhartha Glutamate
Oct 3, 2005

THUNDERDOME LOSER
Hi, I'm Siddhartha Glutamate. You might remember me from such posts as variable is Null or Undefined Has No Properties.

I recently, and foolishly, decided to try and make a simple Javascript game, sort of like Simon except a message will popup with a color, say Red, but it'll be colored Blue and you'd have to click on the blue button. And since I am posting here you can probably figure it has not gone well. I have been trying to make it piece by piece, such as by getting random colors and the names of colors, then having them compared against one another (so that, say, the word red isn't ever colored red) and then moving on to the next part.

The biggest problem I have is that the variable game.playerMoves, which right now logs the color of one of the four options the player has, will at first show the correct selection, but then it will double the selection. So if on the first turn the player clicks on the blue X the log will read "blue" then on the second turn if the player clicks red it will log "blue, red, red" and each additional time through it will log the click multiple times instead of once.

Here is the link to the CodePen.

You have my sincerest thanks for your time and any help you may have to offer.

edit: I should probably say that I am trying to do this in pure JS, I never learned one iota of any of the other forms of JS. Also I've added the code to the post...
edit2: trying to update the code but SA's cloudflare is going nuts on me.

code:
var game = {
  score: 0,
  names: ['Red', 'Blue', 'Green', 'Yellow'],
  nameIndex: [],
  shapes: ['triangle', 'square', 'circle', 'ex'],
  colors: ['red', 'blue', 'green', 'yellow'],
  colorIndex: [],
  moves: [],
  compMoves: [],
  playerMoves: [],
  lastName: [],
  lastShape: [],
  lastColor: [],
  sound:{
    triangle: new Audio('https://s3.amazonaws.com/freecodecamp/simonSound1.mp3'), 
    square: new Audio('https://s3.amazonaws.com/freecodecamp/simonSound2.mp3'), 
    circle: new Audio('https://s3.amazonaws.com/freecodecamp/simonSound3.mp3'), 
    ex: new Audio('https://s3.amazonaws.com/freecodecamp/simonSound4.mp3')
  },
  strict: false,
}

function selector() {
  game.colorIndex = Math.floor(Math.random() * game.colors.length);
  game.nameIndex = Math.floor(Math.random() * game.names.length);
  
  if (game.colorIndex === game.nameIndex) {
    console.log("Sorry, try again.")
    return selector(); }
  else {
    document.getElementById("popUpText").innerHTML = "<h2>"+game.names[game.nameIndex]+"</h2>";
    document.getElementById("popUpText").classList.add(game.colors[game.colorIndex]);
    game.compMoves.push(game.colors[game.colorIndex])
  };
  
  console.log(game.colorIndex);
  console.log(game.nameIndex);
  console.log(game.compMoves)
 }

function numCrunch() {
   document.getElementById("circle").addEventListener("click", function(){
     game.playerMoves.push("p.red");
});
  document.getElementById("ex").addEventListener("click", function(){
    game.playerMoves.push("p.blue");    
});
  document.getElementById("triangle").addEventListener("click", function(){
    game.playerMoves.push("p.green");
});
  document.getElementById("square").addEventListener("click", function(){
    game.playerMoves.push("p.yellow");
});
  console.log(game.playerMoves);
  
}

function clearClass() {
  document.getElementById("popUpText").classList.remove(game.colors[game.colorIndex]);
  document.getElementById("popUpText").innerHTML = " ";
  
}
For some reason trying to add the last function is freaking SA out. So this is what I had in there:

function myTest() { Time out's for selector, numCrunch, and clearClass}. This is so I can click the "Start" button which calls for myTest.

Siddhartha Glutamate fucked around with this message at 08:23 on Jan 11, 2019

Strong Sauce
Jul 2, 2003

You know I am not really your father.






playerMoves is an array. when you print an array in javascript it prints out all the elements separated by a comma. to get the last color chosen from the array, you need to output
code:
game.playerMoves[game.playerMoves.length - 1]
. if you have no need to keep track of all the moves, then you can change that variable into a string containing the color instead of an array.

edit: wait a minute, you don't even call numCrunch, the thing that is duplicating itself in your console log is game.compMoves, which you keep adding onto every time you call "selector()" which is everytime you click the start button...

Strong Sauce fucked around with this message at 05:57 on Jan 11, 2019

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Siddhartha Glutamate posted:

The biggest problem I have is that the variable game.playerMoves, which right now logs the color of one of the four options the player has, will at first show the correct selection, but then it will double the selection. So if on the first turn the player clicks on the blue X the log will read "blue" then on the second turn if the player clicks red it will log "blue, red, red" and each additional time through it will log the click multiple times instead of once.
The linked codepen doesn't include the same code you posted, and doesn't even have responsive buttons.

I think the problem you have (that you described, not from the CodePen) is that you're calling numCrunch before each turn, and you never remove the eventListeners from your buttons, so on the first turn they each have one eventListener, on the second turn they have two, etc.
You could either remove the eventListeners and add them again after each move (which would be good if you want buttons to be nonresponsive while noises are playing or something), or just leave them active until the game is over and not add them repeatedly.

Siddhartha Glutamate
Oct 3, 2005

THUNDERDOME LOSER

Strong Sauce posted:

playerMoves is an array. when you print an array in javascript it prints out all the elements separated by a comma. to get the last color chosen from the array, you need to output
code:
game.playerMoves[game.playerMoves.length - 1]
. if you have no need to keep track of all the moves, then you can change that variable into a string containing the color instead of an array.

edit: wait a minute, you don't even call numCrunch, the thing that is duplicating itself in your console log is game.compMoves, which you keep adding onto every time you call "selector()" which is everytime you click the start button...

roomforthetuna posted:

The linked codepen doesn't include the same code you posted, and doesn't even have responsive buttons.

Sorry about that! I was using both CodePen and MS Visual Code Studio to check my code/tweak stuff and copied and pasted the wrong thing.

I am trying to edit my post but something I am doing is triggering SA's cloudflare. I'll get it sorted out in a moment.

quote:

I think the problem you have (that you described, not from the CodePen) is that you're calling numCrunch before each turn, and you never remove the eventListeners from your buttons, so on the first turn they each have one eventListener, on the second turn they have two, etc.
You could either remove the eventListeners and add them again after each move (which would be good if you want buttons to be nonresponsive while noises are playing or something), or just leave them active until the game is over and not add them repeatedly.

I had to read that twice to actually understand this, and yeah that sounds very reasonable! Thank you!

porksmash
Sep 30, 2008
I'm tearing my hair out trying to figure out what black magic is preventing a basic debounce from working. I have a vue component that can auto-submit data from a form on change. I use Vue's watch feature on the form data, which is just data of the component. I don't want to auto submit every single character as a user is typing in a textbox, so I use lodash.debounce to wrap my function and I should be golden.

What's ACTUALLY happening is that the debounce works great.... once. The first time it expires and actually calls my function, it never seems to reset and will just immediately call and ignore the debouncing completely when data changes. It behaves like this until the page is reloaded. The code is here and you can see it in action here if you mess around with the form while 'auto submit' is on.

Doom Mathematic
Sep 2, 2008
I don't know anything about Vue, but should this.debouncedSetFilters = _.debounce(this.setFilters, 3000); read this.debouncedSetFilters = _.debounce(this.setFilters.bind(this), 3000);? I've seen that kind of thing cause problems many times in the past.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Yes, it's not a vue thing it's a javascript thing. The alternative is to do something like:

code:
this.debouncedSetFilters = _.debounce(() => {
    this.setFilters();
}, 3000);
or:

code:
this.setFilters = this.setFilters.bind(this);
this.debouncedSetFilters = _.debounce(this.setFilters, 3000);

Nolgthorn fucked around with this message at 00:17 on Jan 12, 2019

GeorgieMordor
Jan 23, 2015
I've got a technical screening this Monday and it'll be done exclusively in a JavaScript environment.

Any suggestions on cool and useful stuff to brush up on? I'm very comfortable with JavaScript and use it all the time already, though there's always room for stuff to learn up on.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
I've started looking at technical interviews as a little window into what to expect at the company. Because generally you're going to be talking to leads on the project that are choosing new team members for themselves, they'll throw questions at you that try to get to the bottom of whether you can handle it. A recent interview they kept asking me question after question about bizarre Javascript language behaviours every single one of my answers started with "why would you ever write something like that?"

Turns out the entire tech stack is Javascript that was written ages ago by Java developers who seemed to just throw code at the runtime until it worked and then walked away. Every night now I dream about code I read the day before, like my brain is trying to work it out.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
https://www.codewars.com/

Is my favourite practice website, it proposes you a (often very) simple challenge. You solve it and then it compares you to everyone else's solution, you can vote up and down other people's solutions it's a little like a social network about code. I've found interviewers are happy when I mention it.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
If you want to learn something general and useful I recommend my favourite coding style --procedural--.

Which overall removes the need for state, while not needing to wade into the madness of functional programming. You get all of the same benefits of functional programming while also improving the readability of the code rather than devastating it. It's especially fantastic in Javascript because Javascript has a lot of really useful stuff in it that isn't purely functional in nature.

I see too many people bending over backwards trying to shoehorn the language into a functional style.

As an example of removing state:

code:
function createMyMethod(config) {
	return function myMethod(x, y, z) {
		console.log(config.foo);
	};
}
Can be more simply written, and tested, as such:

code:
function myMethod(config, x, y, z) {
	console.log(config.foo);
}

Adbot
ADBOT LOVES YOU

porksmash
Sep 30, 2008

Nolgthorn posted:

Yes, it's not a vue thing it's a javascript thing.

I'm familiar with `this` and context in JS and that is not actually the problem. All 3 ways of setting up this function (mine + your 2 options) behave identically, actually. This is why I'm so confused. To top it all off the Vue docs themselves actually recommend exactly what I have in my code: https://vuejs.org/v2/guide/computed.html#Watchers

Edit: Ok, solved it. The key was that Lodash debounce returns the previous result if you call it with the same arguments after it has debounced once. Destructuring `val` into a new Object so Lodash detects it as new arguments every call was the solution.

porksmash fucked around with this message at 22:12 on Jan 12, 2019

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply