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
Doom Mathematic
Sep 2, 2008

Boosh! posted:

I am moving my Contentful API calls from my React app to my Express API, merely wrapping my Contentful calls in routes:

code:
app.get('/getAll, (req, res) => {

    client.getEntries({
        content_type: 'presentation',
	limit: 30,
        skip: 0,
    })
    .then((response) => {
	console.log(response)
        res.json(response)
    })

})
With the limit set to 30 it works, but if I bump the limit to 60 or so I get an ERR_EMPTY_RESPONSE error message in my console (doesn't work in Postman either). This was working perfectly fine in my React app but once I moved the calls to Express I started to have this problem. The payload is pretty small, about 60kb and I am able to log it right before sending it. Any idea why this is happening?

EDIT: Seems like any response over 60kb is having this issue vs limit size.

Your code is conspicuously missing a handler for when the promise chain rejects. My suspicion is that either client.getEntries(...) is failing, or response can't be converted to JSON for some reason. I suggest adding a .catch block to properly handle the error case - this may make it easier to diagnose the issue.

Doom Mathematic fucked around with this message at 20:51 on May 7, 2020

Adbot
ADBOT LOVES YOU

Boosh!
Apr 12, 2002
Oven Wrangler

Doom Mathematic posted:

Your code is conspicuously missing a handler for when the promise chain rejects. My suspicion is that either client.getEntries(...) is failing, or response can't be converted to JSON for some reason. I suggest adding a .catch block to properly handle the error case - this may make it easier to diagnose the issue.

Sorry I just left it off here, I have in the code. The getEntries call hasn't failed yet; I am able to console log the response every time from my API:



Seems like once the getEntries payload is over 60k (it works for anything under) it sends nothing. On the client side, I'm getting this error: GET https://api.mysite.com/getAll net::ERR_EMPTY_RESPONSE

I can work around this creating a new, trim object with only the data I need, but I'm still curious as to why this is happening.

Boosh! fucked around with this message at 21:57 on May 7, 2020

necrotic
Aug 2, 2005
I owe my brother big time for this!
Logging to console is not the same as serializing to json. Try to JSON.stringify it and see if that fails.

Boosh!
Apr 12, 2002
Oven Wrangler

necrotic posted:

Logging to console is not the same as serializing to json. Try to JSON.stringify it and see if that fails.

That failed too. I copied the JSON.stringified of it and just tried to res.send it with all the Contentful logic removed and still nothing.

code:
app.get('/getAllReports', (req, res) => {
	res.send(`[{"sys":{"space":{"sys":{"type":"Link","linkTyp........(50-60kb worth of text)........]`)
})
Trimming that string in half worked though. I am not finding anything on send limits, and 60ish kb is nothing.

Doom Mathematic
Sep 2, 2008
I've got no clue why this would be happening but some things I would try to gather more data:

* Make sure res.json/res.send isn't throwing some kind of exception which you're not seeing, by putting console.log lines after it
* Binary chopping your 55kB JSON string down until you have two strings: one which sends, and one, exactly 1 byte longer, which fails. Then see if there's anything weird at that boundary marker, or the size of those two strings
* Send something other than JSON but equivalent in size
* Skip Express and manually res.write the JSON or whatever in discrete chunks, and see if that works
* Double-check the client-size code, maybe post it, and if you're using something high-level, drop down to something lower-level which gives more information about what's happening

go play outside Skyler
Nov 7, 2005


That's weird. My only explanation here would be that you have some additional Express middleware that's causing this issue somewhere. From what I've seen on SO, try listing all your routes and check which middleware could be running and try taking them out one-by-one until it works. Here's apparently how you can list the routes (which should include middleware)

code:
// express 3.x
app.routes

// express 4.x
// Applications - built with express()
app._router.stack

// Routers - built with express.Router()
router.stack
Haven't tested this but it feels like the most probable issue.

Boosh!
Apr 12, 2002
Oven Wrangler
Thanks guys. I’ll try those out and report back.

plasticbugs
Dec 13, 2006

Special Batman and Robin

Boosh! posted:

Thanks guys. I’ll try those out and report back.

If you’re using body-parser, you could try upping the limit with
code:
app.use(bodyParser.json({ limit: '5mb' }))
it’s set pretty low by default- like 100k

You could also try:
code:
app.use(express.json({limit: '5mb'}));

plasticbugs fucked around with this message at 12:24 on May 9, 2020

Doom Mathematic
Sep 2, 2008

plasticbugs posted:

If you’re using body-parser, you could try upping the limit with
code:
app.use(bodyParser.json({ limit: '5mb' }))
it’s set pretty low by default- like 100k

The incoming request is being handled okay. It's the response which they're having problems with.

Tanners
Dec 13, 2011

woof
Does anyone know of a decent library to handle parsing numbers into english words? 10 to ten for example. My research has only turned up sketchy looking libraries but this feels like a common enough problem that there should be a standard.

MrMoo
Sep 14, 2000

The obvious one is number-to-text in npm, did you try that?

idk, this stackoverflow just updated with an answer and a new package too: https://stackoverflow.com/questions/14766951/convert-digits-into-words-with-javascript

MrMoo fucked around with this message at 16:31 on May 12, 2020

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense

MrMoo posted:

idk, this stackoverflow just updated with an answer and a new package too: https://stackoverflow.com/questions/14766951/convert-digits-into-words-with-javascript

I like the code base of that one. mm,

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Nolgthorn posted:

I like the code base of that one. mm,

God that looks so ugly in javascript. Behold the superior c# solution to the problem
code:
using System;
using System.Speech.Synthesis;
using System.IO;
using System.Speech.Recognition;
using System.Speech.AudioFormat;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (MemoryStream streamAudio = new MemoryStream())
            using (SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine(new System.Globalization.CultureInfo("en-US")))
            {
                recognizer.LoadGrammar(new DictationGrammar());

                var fmt = new SpeechAudioFormatInfo(32000, AudioBitsPerSample.Sixteen, AudioChannel.Mono);

                using (SpeechSynthesizer synth = new SpeechSynthesizer())
                {
                    synth.SetOutputToWaveFile(@"C:\temp\test.wav", fmt);

                    Console.WriteLine("Enter number:");
                    var entry = Console.ReadLine();

                    synth.Speak(entry);
                }

                recognizer.SetInputToWaveFile(@"C:\temp\test.wav");
                recognizer.EndSilenceTimeout = new TimeSpan(0, 0, 1);

                var result = recognizer.Recognize();

                foreach (RecognizedWordUnit word in result.Words)
                {
                    Console.Write(word.Text);
                    Console.Write("-");
                }
                
                Console.ReadLine();

            }
        }      
    }
}

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.
I have objects. Some of these objects contain properties which are functions, and these functions return arrays. What I want is an array of objects which has 'expanded out' all of these functions.

code:
let o = {
 a: () => { return [1,2]; },
 b: 'B',
 c: () => { return [ 'hi', 'bye']; }
}

let expanded = expander(o);

expanded = [
 {
  a: 1,
  b: 'B',
  c: 'hi'
 },
 {
  a: 1,
  b: 'B',
  c: 'bye'
 },
 {
  a: 2,
  b: 'B',
  c: 'hi'
 },
 {
  a: 2,
  b: 'B',
  c: 'bye'
 }
]
Any suggestions? I'm having a hard time wrapping my head around this but I'm certain there's ONE WEIRD RECURSION TRICK that will make this not-too-painful.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense

Bruegels Fuckbooks posted:

God that looks so ugly in javascript. Behold the superior c# solution to the problem

How dare you, how, dare, you.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense

Newf posted:

I have objects. Some of these objects contain properties which are functions, and these functions return arrays. What I want is an array of objects which has 'expanded out' all of these functions.

That's a head scratcher. The first thing to do would be ignore the functions part of it, that's irrelevant, and think about having a `base` and set of arrays to work with.

code:
function expander(o) {
    const result = [];
    const base = {};
    const arrs = {};

    for (const key of Object.keys(o)) {
        if (typeof o[key] === 'function') {
            arrs[key] = o[key]();
        } else {
            base[key] = o[key];
        }
    }

    return getAllPermutations(base, arrs);
}
Where essentially you'd be doing some recursive thing ignoring keys that already exist in base and re-using the function with more and more stuff in base. But I started thinking about it and then did something else. I've done this before in the past when working on a javascript based texas holdem calculator but I don't really remember how to generate all possible permutations anymore.

Posting because I tried to do it for a little bit.

dirby
Sep 21, 2004


Helping goons with math

Nolgthorn posted:

Posting because I tried to do it for a little bit.

Thanks for giving me something to start with. I'm pretty inexperienced with Javascript, but if shallow copies of objects are enough, here's a kinda-functional approach that I think works:
code:
let o = {
 a: () => { return [1,2]; },
 b: 'B',
 c: () => { return [ 'hi', 'bye']; }
}

let wrap = (nonfunc) => (() => { return [nonfunc];});
let copy = (input) => Object.assign({},input);
function expander(origobj){
  const obj = copy(origobj);
  let result = [obj];
  for (const key of Object.keys(obj)) {
    if (typeof obj[key] !== "function"){
      obj[key] = wrap(obj[key])
      //obj[key] = (() => {return [ obj[key] ];})//This doesn't work??
    }
    result = result.flatMap((i) => ((obj[key]()).map((t) => Object.assign(copy(i),{[key]:t}))))
  }
  return result
}

console.log(expander(o))
I tried to do away with wrap which I only call once. Can anyone explain why the line I commented out doesn't work in place of the line that calls wrap?

dirby fucked around with this message at 01:32 on May 14, 2020

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!

Newf posted:

Any suggestions? I'm having a hard time wrapping my head around this but I'm certain there's ONE WEIRD RECURSION TRICK that will make this not-too-painful.
You can do it recursively with a generator only moderately painfully.

code:
function* permutations(o) {
  const keys = Object.keys(o);
  function* recurse(i, base) {
    if (i == keys.length) {
      yield base;
      return;
    }
    if (typeof o[keys[i]] == 'function') {
      const arr = o[keys[i]]();
      for (const option of arr) {
        base[keys[i]] = option;
        yield* recurse(i+1, Object.assign({}, base));
      }
    } else {
      base[keys[i]] = o[keys[i]];
      yield* recurse(i+1, Object.assign({}, base));
    }
  }
  yield* recurse(0, {});
}

console.log(Array.from(permutations({
 a: () => { return [1,2]; },
 b: 'B',
 c: () => { return [ 'hi', 'bye']; }
})));
Added bonus of using a generator, if you want to iterate over the permutations you can do it without preallocating a giant list. (And also it's easier to modify to support deep recursion if your objects can be nested - this version doesn't do that.)

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!

dirby posted:

I tried to do away with wrap which I only call once. Can anyone explain why the line I commented out doesn't work in place of the line that calls wrap?
In the commented out line you make obj[key] into a function that returns obj[key], so when you call the function it returns itself.
In the wrap() version you capture the value of obj[key] as a parameter, and then return a function that returns that value, and make obj[key] into that function.
You could do what you wanted without wrap() by doing
code:
const value = obj[key];
obj[key] = (() => [value]);

roomforthetuna fucked around with this message at 01:58 on May 15, 2020

Doom Mathematic
Sep 2, 2008
This was a fun problem! Here is what I came up with, I hope it's legible:

JavaScript code:
const expander = obj =>
  // Iterate over the keys of the object. Each key multiplies the number of
  // possible output objects. (If the value is not a function, then the
  // multiplier is simply 1.)
  Object.entries(obj).reduce(
    (partials, [key, value]) => {
      // What new values are possible for this key?
      const possibleValues = typeof value === 'function' ? value() : [value]

      // For every existing partial object...
      return partials.flatMap(partial =>
        // and every new possible value...
        possibleValues.map(possibleValue => ({
          // create a brand new partial object with that new possible value added to it
          ...partial,
          [key]: possibleValue
        }))
      )
    },

    // At first, having considered none of the input object's keys, there is
    // only one possibility, an empty object
    [{}]
  )
There is plenty of room for optimization here, because as each new object key is considered, an entirely new collection of partials is generated. For example, if the input object is just { a: 1, b: 2, c: 3, d: 4, e: 5 } we end up creating five brand new objects, instead of just adding keys to a single object one at a time. If the total number of objects to be output is very large (which is very possible when you multiply all of the array sizes together) then there is lots of scope for optimization to make this not happen, and to reuse the partials array instead of cloning it lots of times too. But I wouldn't consider going for those optimizations until there's a proper case to be made for them, and some benchmarking comes into play.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
What's missing from that function assuming it works is a disclaimer mentioning that it is not for humans to understand and never touch it.

Doom Mathematic
Sep 2, 2008
Which part do you have trouble understanding?

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
It's returning an array, I think.

Ah, I see you've reduced every value to an array, just a single item for ones that aren't arrays. But then your initial value is an array containing an empty object, assumedly more objects are being added to that array, so why does one need to be included. I don't think an empty object is meant to be a possible result.

And I don't see where permutations are coming from.

Basically I just can't follow the code. It doesn't adhere to the "clean code" methodology, written by that guy that one time. I'm supposed to be able to make sense of each part of what it's doing at a glance.

Nolgthorn fucked around with this message at 01:53 on May 17, 2020

Doom Mathematic
Sep 2, 2008
Apologies! So, here is code which does exactly the same as the above but doesn't abuse array methods so heavily. This also means the comments appear in a more logical order.

JavaScript code:
const expander = obj => {
  // At first, having considered none of the input object's keys, there is
  // only one possibility, an empty object
  let partials = [{}]

  // Iterate over the keys of the object. Each key multiplies the number of
  // possible output objects. (If the value is not a function, then the
  // multiplier is simply 1.)
  const keys = Object.keys(obj)
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i]
    const value = obj[key]

    // What new values are possible for this key?
    let possibleValues
    if (typeof value === 'function') {
      possibleValues = value()
    } else {
      possibleValues = [value]
    }

    const newPartials = []

    // For every existing partial object...
    for (let j = 0; j < partials.length; j++) {
      const partial = partials[j]

      // and every new possible value...
      for (let k = 0; k < possibleValues.length; k++) {
        const possibleValue = possibleValues[k]

        // create a brand new partial object with that new possible value added to it
        const newPartial = Object.assign({}, partial)
        newPartial[key] = possibleValue
        newPartials.push(newPartial)
      }
    }

    partials = newPartials
  }

  return partials
}
We are building an array of possible results. We start from one possible result, an empty object. As we progressively consider each key in the original object in turn, the possibilities increase, so we create a new array of possibilities from the old. So, given input like { a: 1, b: () => [2, 3], c: () => [4, 5] }, this progression goes:

code:
// start
[{}]

// consider all possible ways to add key a to each possibility above
[{ a: 1 }]

// consider all possible ways to add key b to each possibility above
[{ a: 1, b: 2 }, { a: 1, b: 3 }]

// consider all possible ways to add key c
[{ a: 1, b: 2, c: 4 }, { a: 1, b: 2, c: 5 }, { a: 1, b: 3, c: 4 }, { a: 1, b: 3, c: 5 }]
And at the end, we return the final collection of possibilities.

dirby
Sep 21, 2004


Helping goons with math

Nolgthorn posted:

But then your initial value is an array containing an empty object, assumedly more objects are being added to that array, so why does one need to be included.
And I don't see where permutations are coming from.
... I'm supposed to be able to make sense of each part of what it's doing at a glance.
Are you unfamiliar with how to use reduce? Given what the code is doing, the initial value makes a lot of sense to me...

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
I am familiar with reduce. If I wasn't it would have been the first thing I looked up as it was being used........ ?

dirby
Sep 21, 2004


Helping goons with math
Sorry, I was falling asleep and wasn't very clear. I guess I meant something like "This seems like a reasonable/normal way to use reduce. Rather than explaining this code in particular, other similar examples/tutorials of reduce may help you see at a glance how this code is getting all the permutations."

dirby fucked around with this message at 17:33 on May 17, 2020

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.
I am happy that my problem made you scratch your big fat heads. Do not put them away.

Here is my new problem. Less computer-scientific and more engineering.

I'm using webmidi.js to ... listen to midi devices. The problem is that users (read: I) often load the page while plugging my device in. The midi init (which runs on page load) has failed, errors follow, and I have to reload the page so that it picks up the device.

The midi library's `enable` itself takes a callback. My usage is inside Vue components, and I've wrapped the webmidi library inside a singleton, since components that want access to it keep popping in and out of existence (but never exist simultaneously).

JavaScript code:
  private async init(): Promise<boolean> {

    return new Promise<boolean>((resolve, reject) => {
      this.webmidi.enable((err) => {
        if (err) {
          console.log(`Webmidi not enabled: ${err}`);
          reject(err);
        } else {
          console.log(`Webmidi enabled`);

          // Viewing available inputs and outputs
          console.log(`Inputs: ${JSON.stringify(this.webmidi.inputs)}`);
          console.log(`Outputs: ${JSON.stringify(this.webmidi.outputs)}`);

          this.output = this.webmidi.outputs[0];
          this.input = this.webmidi.inputs[0];
          resolve();
        }
      });
    })

  }
This is the async init() function called by my own singleton's constructor. What is best practice for 'waiting' for a device connection here?

Kraus
Jan 17, 2008
I made this for people who want their computer to alert them about the Roman numeral equivalent of a number:

code:

<!DOCTYPE html>

	<script>
	
		n=prompt();

		o="";
	
		d={M:1000,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1};
	
		for(k in d)o+=k.repeat(n/d[k]),n%=d[k];
    
   		alert(o)

		
	
	</script>


EDIT: Also, a version that's still demanding, but doesn't shout at you:

code:

<!DOCTYPE html>

  <script>

      n=prompt();

     

      d={M:1000,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1};

      for(k in d)document.write(k.repeat(n/d[k])),n%=d[k]

     



  </script>

Kraus fucked around with this message at 20:25 on May 21, 2020

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!

Newf posted:

This is the async init() function called by my own singleton's constructor. What is best practice for 'waiting' for a device connection here?
Given that the connect function is presumably not async, I'd just do something like (I can't be bothered to look up the JS specific objects for this right now):
code:
  private async init(): Promise<boolean> {

    return new Promise<boolean>((resolve, reject) => {
      let tries = 5;
      const delayBetweenTriesMs = 1000;
      while(true) {
        console.log(`Waiting for Webmidi: ${err}`);
        // await the thing below if enable is an async function.
        this.webmidi.enable((err) => {
          if (err) {
            tries--;
            if (tries == 0) {
              console.log(`Webmidi not enabled: ${err}`);
              reject(err);
            }
          } else {
            console.log(`Webmidi enabled`);
  
            // Viewing available inputs and outputs
            console.log(`Inputs: ${JSON.stringify(this.webmidi.inputs)}`);
            console.log(`Outputs: ${JSON.stringify(this.webmidi.outputs)}`);
  
            this.output = this.webmidi.outputs[0];
            this.input = this.webmidi.inputs[0];
            tries = 0;
            resolve();
          }
        });
        if (tries == 0) return;
        await delayPromise(delayBetweenTriesMs);
      };
    })

  }
There are library wrapper things for timed retries but they're generally harder to use and harder to follow than just doing it manually like this.

roomforthetuna fucked around with this message at 01:02 on May 22, 2020

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
i dont know much about webmidi.js wrapper but raw webmidi api provides an onstatechange event you can connect to to know when devices hotplug in or out

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.

roomforthetuna posted:

Given that the connect function is presumably not async, I'd just do something like (I can't be bothered to look up the JS specific objects for this right now):

//code

There are library wrapper things for timed retries but they're generally harder to use and harder to follow than just doing it manually like this.

Yes, I think I'll do a timed retry type thing. Will post a trip report over the weekend.

Suspicious Dish posted:

i dont know much about webmidi.js wrapper but raw webmidi api provides an onstatechange event you can connect to to know when devices hotplug in or out

hot drat

e: no, really. it's just to toss my midi init thingy into that onstatechange event if it fails in the first place. Who would have thought to look at the actual browser APIs?

Newf fucked around with this message at 04:34 on May 23, 2020

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.
FUN FACT 1: the MIDIAccess object returned by navigator.requestMIDIAccess is not a singleton, so when you are setting it's onstatechange handler you'd better not assume that you'll be overwriting the existing onstatechange handler. Instead, you are adding more and more handlers!

FUN FACT 2: A web browser can query USB devices / ports heavily enough that the computer (Windows 10) stops recognizing the insertion or removal of any usb device from any port! The computer will then take ~40 minutes of shut down only to arrive at a BSOD (driver_power_state_failure) who stalls at 0% in its information gathering phase overnight.

Happily, the computer seems fine after a hard boot.

Tuxedo Gin
May 21, 2003

Classy.

Sorry for what is likely a stupid question. I am totally new to JS. I have an array of strings which contain HTML (comes in via a variable in Django). What is the best way to list them (and have the HTML work, if possible)? I tried just doing a for loop through the array that appended them all to a list, but couldn't get it to display anything.

Roadie
Jun 30, 2013

Tuxedo Gin posted:

Sorry for what is likely a stupid question. I am totally new to JS. I have an array of strings which contain HTML (comes in via a variable in Django). What is the best way to list them (and have the HTML work, if possible)? I tried just doing a for loop through the array that appended them all to a list, but couldn't get it to display anything.

The really dead simple version:

JavaScript code:
document.querySelector('#id-of-some-div-here').innerHTML = arrayOfHtmlStrings.join('\n')
Standard caveats apply here of this making it real easy to accidentally break the page and/or allow site vulnerabilities if there's bad HTML from the source.

The 'good' way (which is also the approach used by various rich text editors these day) is to have the data instead be an array of JSON objects that you can parse for specific output:

HTML code:
<div id="wrapper-element"></div>

<script>
  const pageValues = [
    { type: "header", value: "Here's a header" },
    { type: "text", value: "Here's some text" },
    { type: "hr" },
    { type: "text", value: "Here's some more text" },
  ];

  const wrapperElement = document.querySelector("#wrapper-element");

  pageValues
    .map((entry) => {
      switch (entry.type) {
        case "header":
          const element = document.createElement("h1");
          element.appendChild(document.createTextNode(entry.value));
          return element;
          break;

        case "text":
          return document.createTextNode(entry.value);
          break;

        case "hr":
          return document.createElement("hr");
          break;
      }

      return null;
    })
    .filter((output) => output !== null)
    .forEach((output) => {
      wrapperElement.appendChild(output);
    });
</script>
This way you're relying on built-in browser behavior for sanitizing text, you're whitelisting specific output elements, and so on.

Take this approach a bit further and you get HyperScript (which is philosophically doing basically the same thing as above, just with way more helpers and abstraction), and then take HyperScript further and you get React, which adds more abstraction layers and the power of state management but still basically centers around parsing arrays and turning them into sets of HTML node objects.

Roadie fucked around with this message at 11:01 on May 24, 2020

Tuxedo Gin
May 21, 2003

Classy.

Roadie posted:

The really dead simple version:

Standard caveats apply here of this making it real easy to accidentally break the page and/or allow site vulnerabilities if there's bad HTML from the source.

The 'good' way (which is also the approach used by various rich text editors these day) is to have the data instead be an array of JSON objects that you can parse for specific output:

This way you're relying on built-in browser behavior for sanitizing text, you're whitelisting specific output elements, and so on.

Take this approach a bit further and you get HyperScript (which is philosophically doing basically the same thing as above, just with way more helpers and abstraction), and then take HyperScript further and you get React, which adds more abstraction layers and the power of state management but still basically centers around parsing arrays and turning them into sets of HTML node objects.

Thank you for the reply. I've got a lot to read up on and learn from.

Kraus
Jan 17, 2008
Hey guys, should I submit this to ECMA as an improvement to JavaScript?

code:

sumDigits=n=>{

s=0;

for(d of n.toString())s+=1*d;

return s

}

alert(sumDigits(1234)) //10

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself
what?

go play outside Skyler
Nov 7, 2005


Better to make it an npm package with 5 dependencies

Adbot
ADBOT LOVES YOU

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Kraus posted:

Hey guys, should I submit this to ECMA as an improvement to JavaScript?

to be a true js professional, you need one of the following methods in every single line of code - map, reduce, or filter
e.g.
code:
sumDigits= (n) => n.toString().split("").reduce( (prev, curr) => Number(prev) + Number(curr)); 

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