I am new to node.js, ajax, and asynchronous code. I’ve pieced together a working way to exchange json between browser and server and am wondering if someone with more experience considers the approach reasonable for my needs.

Requirement Context:  This technique will be used for back-office update of data. Initially there will be one user on the same computer as the database. I’d rather not rule out allowing a few other users to remotely update the backend in the future, but if that happens, they would use simpler screens designed with the remote location in mind. Since this is back-office, I can insist on the latest Chrome browser.

My limitations:  I’m a one-man shop developing/supporting a website in semi-retirement. I am part-time and my responsibilities extend beyond coding, so at best I can be a jack of some trades, but master of none.

**You can skip straight to “Requirement” below**, or if you want more context, read on:

Why Not Use a Library to Do This?: I am open to being told that I should, but prefer to avoid libraries unless there is compelling reason to use them. I’m a 1-man shop who needs to figure out how to do a handful of things and then automate doing them again and again. It’s a very different situation than a large company doing a multitude of things. For example, the front-end of this application has half a million static web pages written by the back-end. There are only half a dozen page types and each loads with a single hit to the server. They are written with plain vanilla html, css, and javascript. The menus would look nicer if a library were used (or when I spend more time on them), but there is value in the simplicity. Libraries complicate version control, typically provide enormous capability I will never use, and drag along legacy support I don’t need. My personal experience is that relative to many others, I am better at going a little deeper on one product than I am at remembering how multiple products interface.

Tool Rationale:  There are no plans for the site to generate revenue, so one of the reasons I chose MySQL and node.js is that there is no licensing costs for a hobby I hope to continue for twenty years. The tools seem up to my requirements and are popular enough that I can find ways of doing things on the internet. Also, as a pat-time, 1-man shop, being able to use the same language on the server and browser is an enormous advantage. 

**Requirement:**  With plain vanilla node.js move large json files between browser and server to support backend data maintenance for a website. I have tested the current solution and it moves more data than I need to move more quickly than I need to move it. (I tested 100,000 objects requiring 8Meg json files both ways.) But I have no ajax experience and fear there might be problems I’m not foreseeing or easy ways to do this kind of ajax in a better way.

Issues I considered:

 - CORS requires that the server that responds to an ajax request, must first have served the html file making the request.
 - Ajax POSTs are idempotent
 - The browser will automatically call for a favicon

On the server, the switch statement is going to get too long if I keep adding cases for each maintenance page. I’ll clean that up and welcome any general advice you’re willing to offer, but my question here is if the ajax technique is reasonable for my needs?

I’m including colorized-VSCode images of the code to make reading it easier, as well as actual code you can copy to a computer and run. The sample code can be tested as is by putting the .js and .html file in the same directory. Where * is “test_ajax_post_json_sans_form”, you can then test by:  executing node *.js in the command console, and then loading http://localhost:8000/* in your browser. I used Chrome.

html with client code image:
[![enter image description here][1]][1]

js image:
[![enter image description here][2]][2]

I included the code in snippets, but it requires node.js to run, so you'd have to copy it to a computer with node.js:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

    'use strict';
    const host = 'localhost';
    const http = require('http'); // VSCode shows 3 dots under "require" and says something about NodeRequire???
    const fs   = require('fs').promises;
    const port = 8000;

    const requestListener = function (req, res) {
        switch (req.url) {
            case "/test_ajax_post_json_sans_form.html": // serve an intial html file
                fs.readFile(__dirname + '/test_ajax_post_json_sans_form.html')
                .then(contents => {
                    res.writeHead(200, {'Content-Type': 'text/html'});
                    res.end(contents);
                })
                .catch(err => {
                    res.writeHead(500);
                    res.end(err);
                    return;
                });
                break
            case '/test_ajax_post_json_sans_form.html/ajaxTest1': // receive json, process, then return other json
                let body = '';
                req.on('data', (data) => {
                    body += data;
                });
                req.on('end', () => {
                    console.log(body);  // to show all data has arrived
                    // here we will check or errors, create a complex return-object, stringify it, and send it back
                    const objToReturn = {data1: 'Test message from server', data2: 'could be a complex json object'};
                    res.writeHead(200, {'Content-Type': 'application/json'});
                    res.end(JSON.stringify(objToReturn));
                });         
                break
            case '/favicon.ico':
                // browser will call favicon automatically. This satisfies the request (though its failing
                //   won't keep the ajax from working).
                fs.readFile(__dirname + '/favicon.ico')
                .then(contents => {
                    res.writeHead(200, {'Content-Type': 'image/x-icon'});
                    res.end(contents);
                })
                .catch(err => { // lacking favicon will not impact test
                    res.writeHead(200, {'Content-Type': 'image/x-icon'});
                    res.end();
                });
                break
            default:
                res.writeHead(404);
                res.end(JSON.stringify({error:'Resource not found'})); // in production, might load a not-found page here
        }
    } 
    const server = http.createServer(requestListener);
    server.listen(port,host, () => { // binds the server object to a newtwork address
        console.log(`Server is running on http://${host}:${port}. (^c to cancel)`);
    });


<!-- language: lang-html -->

    <!DOCTYPE html><body>
        <button type="button" id="idSubmitButton">Send and then Receive JSON</button>
        <br>After clicking the button, the JSON string sent from the browser to the server will show in the console.
        <br>Then the JSON response string from the server will replace what is below.
        <br><br>
        <div id='idDisplay'>
            innerHTML to replace via ajax
        </div>

        <script>
            'use strict';
            function exchangeJSON() {
                idSubmitButton.disabled = true // assure post isn't sent again prior to a response
                // here a complex object could be built
                const testObjToSend = {message1: 'Test message from browser', message2: 'could be a complex JSON string'};
                const xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function () {
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        // this is where the received responseText can be manipulated to update the page
                        document.getElementById('idDisplay').innerHTML = xhr.responseText; // demonstrate json arrived
                        idSubmitButton.disabled = false // post completed, so enable posting again
                    }
                }
                xhr.open('POST', 'test_ajax_post_json_sans_form.html/ajaxTest1', true);
                xhr.setRequestHeader('Content-Type', 'application/json');
                xhr.send(JSON.stringify(testObjToSend));
            }
            const idSubmitButton = document.getElementById('idSubmitButton');
            idSubmitButton.addEventListener('click', function () {
                exchangeJSON() ;
            });
        </script>
    </body></html>

<!-- end snippet -->

  [1]: https://i.sstatic.net/evKoz.png
  [2]: https://i.sstatic.net/mUpA2.png