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
Dominoes
Sep 20, 2007

necrotic posted:

Avoiding bundlers is going to make things very painful for you. Just use parcel, you'll be much happier in the long run.
This attempt appears to have failed due to the issue I posted above... Last time I checked (1.5 years go), browsers didn't even support es6 imports. Looks like we're close now; working through an $export is not a function error in Parcel. Parcel seems like an improvement in simplicity over CRA and Webpack. edit: Now getting require(...).Object is undefined

Dominoes fucked around with this message at 00:44 on Jul 6, 2018

Adbot
ADBOT LOVES YOU

Chenghiz
Feb 14, 2007

WHITE WHALE
HOLY GRAIL
Parcel is nice for smaller projects but webpack isn't going anywhere soon, it's too flexible.

tracecomplete
Feb 26, 2017

(s h a m e l e s s p l u g)

I come mostly from a Ruby and Java universe where stuff like "background jobs processing" is easy - use Sidekiq or Quartz or whatever, you're done. NodeJS has a few tools, chiefly Kue and Bull...but I've never been satisfied with them. So I wrote and open-sourced (with some additional features behind a paywall so as to give me a financial reason to maintain the project over the long term) TaskBotJS, which for my money is the best option out there for TypeScript and JavaScript.

I use the open-source version myself in one project to keep tabs on it and the commercial version in another because I need the features there, so it's dogfooded, and I have other folks using it already so it's not a Works On My Machine situation. (Except for the packaging and release stuff. Which is awkward because that's also the best one-stop demo of the project. But hey--it's an 0.9.0 release, not a 1.0 release.)

Feel free to check it out and let me know what you think. https://github.com/eropple/taskbotjs

Dominoes
Sep 20, 2007

Chenghiz posted:

Parcel is nice for smaller projects but webpack isn't going anywhere soon, it's too flexible.
Couldn't get parcel to work; switched to Webpack 4 and ts-loader; works with a short webpack.config.js.

Roadie
Jun 30, 2013

Dominoes posted:

Thanks dudes. This appears to be an issue of TSC not knowing how to deal with importing node modules as files, and es6 imports having the opposite problem; diagnosing by editing the compiled files directly to point to .js files. Fighting a mime issue now. (And will have to re-attack how to workaround this).

Roadie: That TSconfig setting sounds lovely! The import * as syntax is awk. I'm hoping to avoid bundlers entirely (not realistic?), but Parcel looks nice from a skim.

tsc isn't meant to be used on large project without a bundler. Its remit is to handle TS->JS transpilation, and anything else is incidental.

Chenghiz posted:

Parcel is nice for smaller projects but webpack isn't going anywhere soon, it's too flexible.

I suspect Parcel won't last forever, but for now it's good for giving Webpack a kick in the rear end about how Goddamn overcomplicated it is just to do "the right thing" of handling HTML, JS, SCSS/LESS, and images properly, and it not taking a bunch of screwing around to handle the simple use case of two HTML files with different bundles.

Edit: I wish somebody would make something to reduce the endless proliferation of config files because I can't actually trust the full ecosystem for any of my tools to just read a Goddamn entry in package.json. .babelrc, .browserslistrc, .eslintrc, .prettierrc, .stylelintrc...

Roadie fucked around with this message at 05:20 on Jul 7, 2018

Dominoes
Sep 20, 2007

Roadie posted:

Edit: I wish somebody would make something to reduce the endless proliferation of config files because I can't actually trust the full ecosystem for any of my tools to just read a Goddamn entry in package.json. .babelrc, .browserslistrc, .eslintrc, .prettierrc, .stylelintrc...
My goal is getting WASM working properly with Rust so I can avoid as much node-based tooling as possible.

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!
I just learned async/await. It makes regular Promises look stupid (except for those edge things where you have to put a Promise around some old callback-type function to make it async-able.) But for like 95% of asynchronous things it's great. And especially for unit tests, where promises are loving terrible.

tracecomplete
Feb 26, 2017

util.promisify exists for promisifying callbacks on Node. Something similar no doubt exists in a browser (but I rarely run into them anymore there).

Odette
Mar 19, 2011

AFashionableHat posted:

util.promisify exists for promisifying callbacks on Node. Something similar no doubt exists in a browser (but I rarely run into them anymore there).

Node is slowly rolling out promisified versions of their API. I think the most recent module that was mainlined is fs.

Can't wait to see the end of callbacks.

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

roomforthetuna posted:

I just learned async/await. It makes regular Promises look stupid (except for those edge things where you have to put a Promise around some old callback-type function to make it async-able.) But for like 95% of asynchronous things it's great. And especially for unit tests, where promises are loving terrible.

Async uses Promises under the hood. Makes you think.

MrMoo
Sep 14, 2000

Mixing async await with Promise chains is the way to go, I don't understand when people want to go all in on just one or the other.

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!

Lumpy posted:

Async uses Promises under the hood. Makes you think.
I knew that, and it did make me think, mostly I wonder how that works with something like this:
code:
for (let i = 0; i < 5; i++) {
  await someFunc[i]();
  console.log(i);
}
Mapping that to Promises seems tricky. I mean I could write something with Promises that does that, but mapping it automatically, specifically, seems tricky.

FSMC
Apr 27, 2003
I love to live this lie
I'm trying to create a function that traverses all the child nodes but the for loop seems to return early. I'm just getting into js and not sure if I've just made a simple mistake here or if js works differently than I think it should.
code:
/* I think for some reason js has issues with recursive functions and for loops. it just exits the loops after one recursion. 
 */
function recursiveNode(node) {

    children = node.childNodes;

    for (var i = 0; i < children.length; i++) {
        console.log("loop : " + i);
        child = children[i];
        console.log("index: " + i + "/" + children.length + "element: " + child.textContent + " val : " + child.innerHTML);
        recursiveNode(child);
    }
}

necrotic
Aug 2, 2005
I owe my brother big time for this!
JS has nothing special with recursion. What you're seeing is variable hoisting at work: both your children and child variables lack a declaration and are hoisted to the parent (global) scope. You can fix this by adding var declarations at the top of your function:

code:
function recursiveNode(node) {
  var child;
  var children = node.childNodes;

  for...
}
Without that the var declarations implicitly happen before the function declaration.

You could also use forEach instead of a loop and remove any explicit declarations:

code:
function recursiveNode(node) {
  node.childNodes.forEach((child, i) => {
    recursiveNode(child);
  });
}

necrotic fucked around with this message at 13:22 on Jul 14, 2018

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

roomforthetuna posted:

I knew that, and it did make me think, mostly I wonder how that works with something like this:
code:
for (let i = 0; i < 5; i++) {
  await someFunc[i]();
  console.log(i);
}
Mapping that to Promises seems tricky. I mean I could write something with Promises that does that, but mapping it automatically, specifically, seems tricky.

That's why I let all the people who are smarter than me (which is a whole lot of people!) make stuff like Babel.

Doom Mathematic
Sep 2, 2008

FSMC posted:

I'm trying to create a function that traverses all the child nodes but the for loop seems to return early. I'm just getting into js and not sure if I've just made a simple mistake here or if js works differently than I think it should.
code:
/* I think for some reason js has issues with recursive functions and for loops. it just exits the loops after one recursion. 
 */
function recursiveNode(node) {

    children = node.childNodes;

    for (var i = 0; i < children.length; i++) {
        console.log("loop : " + i);
        child = children[i];
        console.log("index: " + i + "/" + children.length + "element: " + child.textContent + " val : " + child.innerHTML);
        recursiveNode(child);
    }
}

Separately from what necrotic said, you should be using some kind of linter. Any linter would instantly have caught this issue. JavaScript has gotchas, and it's highly inadvisable not to use the industry standard tools for avoiding those gotchas.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

roomforthetuna posted:

I knew that, and it did make me think, mostly I wonder how that works with something like this:
code:
for (let i = 0; i < 5; i++) {
  await someFunc[i]();
  console.log(i);
}
Mapping that to Promises seems tricky. I mean I could write something with Promises that does that, but mapping it automatically, specifically, seems tricky.

I've seen how TS transpiles async await to ES5, and it uses a massive switch case based on state at any given time that keeps adding itself to the event loop until it's done

FSMC
Apr 27, 2003
I love to live this lie

Doom Mathematic posted:

Separately from what necrotic said, you should be using some kind of linter. Any linter would instantly have caught this issue. JavaScript has gotchas, and it's highly inadvisable not to use the industry standard tools for avoiding those gotchas.

I've read up on variable hoisting so I think I have some kind of handle of why it didn't work. "children" is assigned outside of the for loop, but because I forgot to write var, it became a global value, so when it was updated in the inner loop with length 0, the for loops returns after the first loop. I'm pretty new to js but that seems like crazy bad.

I'm pretty sure I had some sort of LINT maybe jslint installed but when I checked I had some warnings about eslint not being installed. So I managed to get that installed which then told me to install tslint, which made me also install typscript, and then finally seemed all installed but not much help. I tried a to create an unused variable, created a typo, missed out semi colons and vscode highlights all the other mistakes, but there is nothing in the problems log or on the screen about potential scope issues. So I have got the same warnings as I would have had before.

I'm using vscode and pretty new to js and using lint. Is there some sort of setting I can use to catch stuff like this. I would have expected that using a variable without declaring it would be bad and show a warning, also shouldn't any globals throw up a warning?

Also I'm confused by some of the notation in the fix and lots of javascript examples I've seen. I've tried to find more information about it but I don't know the terminology or topic names I need to be looking for.
*Where function variable brackets aren't closed out. "(variable, function .... {.....});"
*What does the "=>" mean

code:
  node.childNodes.forEach((child, i) => {
    recursiveNode(child);
  });

necrotic
Aug 2, 2005
I owe my brother big time for this!
That is shorthand function syntax. You could replace it with


code:

forEach(function(child, i) {
})

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!

FSMC posted:

*What does the "=>" mean
(aaa, bbb) => {some stuff}
is mostly equivalent to
function (aaa, bbb) {some stuff}

Except the arrow version doesn't have its own "this" and "arguments" bindings, it inherits those from its scope, where the "function" version has its own. 90% of the time it doesn't matter, and 90% of the *rest* of the time, the arrow version is more likely to be what you expected than the "function" version.

(There are some other differences you almost certainly don't care about at this level.)

Edit: also the thing to search for if you want to learn more about it is "arrow functions".

roomforthetuna fucked around with this message at 04:19 on Jul 15, 2018

FSMC
Apr 27, 2003
I love to live this lie

necrotic posted:

That is shorthand function syntax. You could replace it with

code:
forEach(function(child, i) {
})

I think the main issue I have is I don't understand what the full hand means. I've seen this sort of fullhand notation everywhere in js but don't understand it at any level.
Here is the original function which works as I expect.
code:
function recursiveNode(node) {
    var children = node.childNodes;
    for (var i = 0; i < children.length; i++) {
        recursiveNode(children[i]);
    }
}
Here is pseudo code of what I expect a more streamlined syntax to look like.
code:
function recursiveNode(node) {
    var children = node.childNodes;
    for child in children {
        recursiveNode(child);
    }
}
//OR
function recursiveNode(node) {
    var children = node.childNodes;
    children.forEach() {
        recursiveNode(child);
    }
}
The main issue is I don't understand why or where functions are declared. Why are functions are decalred where I would expect a variable to be. So if I was going to declare a function, why not just declare it separately?
code:

function simple(node){
    console.log("calling recursive on :" + child.innerHTML);
    recursiveNode(child);
}
function recursiveNode(node) {
    var children = node.childNodes;
    children.forEach() { child |
        simple(child);
    }
}

Doom Mathematic
Sep 2, 2008

FSMC posted:

Here is pseudo code of what I expect a more streamlined syntax to look like.
code:
function recursiveNode(node) {
    var children = node.childNodes;
    for child in children {
        recursiveNode(child);
    }
}
//OR
function recursiveNode(node) {
    var children = node.childNodes;
    children.forEach() {
        recursiveNode(child);
    }
}
The main issue is I don't understand why or where functions are declared. Why are functions are decalred where I would expect a variable to be.

In this case, forEach is no special piece of syntax. It is just a method on children (and on any array, in fact). We call this method passing a single argument, and that single argument is itself a function. In other words forEach is a "higher-order function". The way forEach behaves is that it calls the "inner function" once per element in the array.

Supporting this, JavaScript does, as you say, allow functions to be declared pretty much anywhere you would expect a simple JavaScript value or expression like 5 + 6. You can then bind that value to a variable e.g. var simple = function (child) { ... } and pass the variable to other functions children.forEach(simple), or just cut out the middleman: children.forEach(function (child) { ... }).

You can declare all your functions separately if you like, there are some pros and cons to doing this, but you should get used to people declaring them in-line as well.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

FSMC posted:


The main issue is I don't understand why or where functions are declared. Why are functions are decalred where I would expect a variable to be. So if I was going to declare a function, why not just declare it separately?


There is no reason why you couldn't just declare it separately.

Some reasons to use anonymous functions:

1. It's not used anywhere else.
2. It has access to its parent scope.
3. It is standard JS practice.

As mentioned, you better get used to using them because of #3. You're going to see them everywhere. I agree that its pretty visually noisy. Arrow functions help with that though.

Roadie
Jun 30, 2013

FSMC posted:

The main issue is I don't understand why or where functions are declared. Why are functions are decalred where I would expect a variable to be. So if I was going to declare a function, why not just declare it separately?

To help with the context you're missing here, functions in JS are just objects like everything else. These two things...

JavaScript code:
function whateverFunction() {
  console.log('whatever')
}
JavaScript code:
const whateverFunction = function() {
  console.log('whatever')
}
...are 99% identical for practical purposes. The only real difference in use is that the second one won't have a .name property on the function (which you generally won't be looking at for debugging purposes anyway because of minifiers), and the first one is hoisted so that you can refer to whateverFunction before the line it's actually defined in the code (useful for recursive stuff).

Munkeymon
Aug 14, 2003

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



Thermopyle posted:

There is no reason why you couldn't just declare it separately.

Some reasons to use anonymous functions:

1. It's not used anywhere else.
2. It has access to its parent scope.
3. It is standard JS practice.

As mentioned, you better get used to using them because of #3. You're going to see them everywhere. I agree that its pretty visually noisy. Arrow functions help with that though.

#2 is the most important IMO. Closures are really powerful once you understand how to use them with callbacks passed to higher-order functions like forEach.

Dr. Poz
Sep 8, 2003

Dr. Poz just diagnosed you with a serious case of being a pussy. Now get back out there and hit them till you can't remember your kid's name.

Pillbug
I've got an array and a bunch of conditions to potentially filter it on. I'd like to compose them together in something like:

code:
stuff
	.filter(t => !searchString)
	.filter(notSelected)
	.filter(otherFilter)
	.filter(finalFilter);
It makes the syntax readable but I feel uncertain about performance implications. Is this something the runtime will sort out for me or should I combine these into a less readable but better performing single filter?

Munkeymon
Aug 14, 2003

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



Depends on how big you expect the array to be and how often the code runs! Luckily, browsers have great tooling nowadays to profile your code and figure out whether it's a performance bottleneck or not.

Osmosisch
Sep 9, 2007

I shall make everyone look like me! Then when they trick each other, they will say "oh that Coyote, he is the smartest one, he can even trick the great Coyote."



Grimey Drawer
In case of lodash you can also use the lazy evaluation chain which could help a lot. But yeah, when in doubt profile.

MasterSlowPoke
Oct 9, 2005

Our courage will pull us through
Is there a good tutorial on how to organize a react application? I'm coming from a hyper-structured Rails back and this all feels kinda like the wild west.

kitten emergency
Jan 13, 2008

get meow this wack-ass crystal prison

MasterSlowPoke posted:

Is there a good tutorial on how to organize a react application? I'm coming from a hyper-structured Rails back and this all feels kinda like the wild west.

use create-react-app imo

geeves
Sep 16, 2004

FSMC posted:

function recursiveNode(node) {
var children = node.childNodes;
children.forEach() {
recursiveNode(child);
}
}
[/code]

Careful with forEach on a NodeList it's not exactly the same as an array. Babel probably takes care of this, but just in case, you probably are safer with:

code:
var children = Array.from(node.childNodes);
children.forEach((child) => {})

MasterSlowPoke
Oct 9, 2005

Our courage will pull us through

uncurable mlady posted:

use create-react-app imo

Sounds perfect, thanks!

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!

geeves posted:

Careful with forEach on a NodeList it's not exactly the same as an array. Babel probably takes care of this, but just in case, you probably are safer with:
I don't know why you'd even use forEach these days, now that there's the "for (x of y)" syntax, other than ingrained habit from The Time Before.
forEach is horrible to debug and horrible to reason about.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
The performance of for...of is terrible, since it requires an allocation on each loop, and next() has not been optimized in most engines. forEach and for loops don't have that issue. I've gotten multi-FPS speedups by changing for...of to forEach in some of my work.

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!

Suspicious Dish posted:

The performance of for...of is terrible, since it requires an allocation on each loop, and next() has not been optimized in most engines. forEach and for loops don't have that issue. I've gotten multi-FPS speedups by changing for...of to forEach in some of my work.
That seems weird, can you elaborate? Why does for...of require an allocation each time? It seems like
for (let a of list) { ... }
should be equivalent to
for (let i = 0; i < list.length; i++) {let a = list[i]; ... }
except for not taking up any namespace for i.

(Edit: if the 'a' is the allocation then I would think forEach would require the same allocation for the 'a' in list.forEach((a) => { ... }).)
(Edit2: are you think of it as it applies to key-values rather than arrays, where you have to do Object.keys(map) and *that's* the allocation? I do see the value in forEach for key-value situations.)

roomforthetuna fucked around with this message at 22:30 on Jul 18, 2018

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
for (const a of list) is equivalent to:

JavaScript code:
const _iter = list[Symbol.iterator]();
while (true) {
    const _item = _iter.next();
    const a = _item.value;
    // loop body
    if (_item.done)
        break;
}
There is no specialization for arrays in common engines yet. The allocation happens in the list[Symbol.iterator] call, and also _list.next.

Suspicious Dish fucked around with this message at 22:36 on Jul 18, 2018

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!
Aha, thanks for the explanation. And that makes me sad.

geeves
Sep 16, 2004

roomforthetuna posted:

I don't know why you'd even use forEach these days, now that there's the "for (x of y)" syntax, other than ingrained habit from The Time Before.
forEach is horrible to debug and horrible to reason about.

When I say forEach, I guess I should have clarified all of the array methods including map, reduce and filter. Usually if I'm using forEach I just use a regular loop given performance https://jsperf.com/fast-array-foreach

Happy Thread
Jul 10, 2005

by Fluffdaddy
Plaster Town Cop
Wow, are those jsperf measurements for real? That difference is severe. I thought for sure JS engine would just optimize most cases to do the same thing as a for loop since in a lot of cases the programmer is just going to blindly use whichever syntax is their preference at the moment.

So it seems like most people's uses of for( x of y ) and forEach() out there would just be done upon plain old arrays in the most mundane way possible, yet the engine always assumes you might have some special type of list with an overridden custom iterator and runs it the really slow way just to be careful? Is that what's going on?

Does this mean if I go back in all my inner loops and turn all for( x of y ) and forEach() calls (where I was just trying to save an unnecessary counter variable) into for loops instead, I could have as big of speed gains as those graphs show?

Adbot
ADBOT LOVES YOU

geeves
Sep 16, 2004

Dumb Lowtax posted:

Wow, are those jsperf measurements for real? That difference is severe. I thought for sure JS engine would just optimize most cases to do the same thing as a for loop since in a lot of cases the programmer is just going to blindly use whichever syntax is their preference at the moment.

So it seems like most people's uses of for( x of y ) and forEach() out there would just be done upon plain old arrays in the most mundane way possible, yet the engine always assumes you might have some special type of list with an overridden custom iterator and runs it the really slow way just to be careful? Is that what's going on?

Does this mean if I go back in all my inner loops and turn all for( x of y ) and forEach() calls (where I was just trying to save an unnecessary counter variable) into for loops instead, I could have as big of speed gains as those graphs show?

Pretty certain it's accurate. The slowdown is mostly because of the instantiation and tear down of a method for each iteration that comes with scope built in to forEach. If you had to build in a closure into a for loop for any reason you might see some slowdown as well (how much compared to forEach, I don't know, TBH).

Unless your data set is extremely large, it's probably nothing to worry about, but if you're getting into 10,000s of calculations then start maybe start to think about performance (and really shouldn't be done on the front end if at all possible)

We wrote a custom calendar-like thing in react that in some rare cases had several thousand datapoints displayed. We took raw solr data and with map / foreach transformed it into something useful (this actually was harder to do in Java but very easy with JS). The TTI was still pretty decent in these edge cases at 2-3 seconds.

geeves fucked around with this message at 02:08 on Jul 19, 2018

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