Home > Blockchain >  Ajax Requests with node server in another folder
Ajax Requests with node server in another folder

Time:12-19

So i'm new in JS and i have a task for mastering Ajax Requests.I should send an email input from form to the server and a lot more,but i can not figure out how to send this data to a server that is in another folder.I lost all my nerves with this task and i dont know what to do. So,i have a folder personal-website-server and another folder src where is my project,both folders are in another folder,the parent. It looks like this :
./
dist < webpack bundle folder
node_modules
personal-website-server
/ package.json in personal-website-server
src
and package.json in the parent folder Image for more understanding:
enter image description here

So,i should do this:
Upon clicking on the "Subscribe" button, implement the functionality for sending a user email to the server. For that, make POST Ajax request using http://localhost:3000/subscribe endpoint. The call to the server should only be made when the form is valid (the validate function )
The connection is made through a proxy to the server,idk how this thing works and i get it hard to do this task because its not so described.
Codes:
I created fetch.js in src that checks if email is valid and sends it to the server,like i understood:

import { validateEmail } from './email-validator.js'

// const express = require('express');
// const app = express();
// app.listen(3000,() => console.log('listening at 3000'));
// app.use(express.static(path.join(__dirname, 'public')));

export const sendSubscribe = (emailInput) => {
    const isValidEmail = validateEmail(emailInput)
    if (isValidEmail === true) {
        // fetch('http://localhost:9000/subscribe', {
        //     method: 'post',
        //     body: emailInput
        // }).then(function (response) {
        //     return response.text();
        // }).then(function (text) {
        //     console.log(text);
        // }).catch(function (error) {
        //     console.error(error);
        // })

        //createRequest(url);

        app.post('/subscribe', (request, response) => {
            console.log(request.body);
        });


    }
}

// const createRequest = (url) => {
//     const httpRequest = new XMLHttpRequest(url)
//     httpRequest.addEventListener('readystatechange', (url) => {
//         if (httpRequest.readyState === 4) {
//             console.log(httpRequest.responseText)
//         }
//     }); httpRequest.open('GET', url);
//     httpRequest.send();
// };

But this code app is also in personal-website-server task,so i dont know how to make the connect from my app to that server.
Section where my form is available:

import { subscribe, unsubscribe, subscribeEmail } from './subscribe.js'
import { sendSubscribe } from './fetch.js'

const addSection = () => {
  const sectionFour = createElement('sectionFour', 'section', 'app-section app-section--image-program', 'fourth-section')
  const sectionParent = getElbyID('sectionParent', 'third-section')
  const parentSection = sectionParent.parentNode
  parentSection.insertBefore(sectionFour, sectionParent.nextSibling)

  const heading2 = createElement('heading2', 'h2', 'program-title')
  const heading2Text = document.createTextNode('Join Our Program')
  heading2.append(heading2Text)
  const parent = getElbyID('parent', 'fourth-section')

  const heading3 = createElement('heading3', 'h3', 'program-subtitle')
  const heading3Text = document.createTextNode('Sed do eiusmod tempor incididunt')
  heading3.appendChild(heading3Text)
  const linebreak = createElement('linebreak', 'br')
  heading3.appendChild(linebreak)
  const textAfterBreak = document.createTextNode('ut labore et dolore magna aliqua')
  heading3.appendChild(textAfterBreak)

  const form = createElement('submitFieldWrapper', 'form', 'submitFieldWrapper', 'form')
  form.method = "POST";
  parent.append(heading2, heading3, form)

  const emailForm = createElement('emailForm', 'div', 'form-wrapper', 'emailForm')

  const inputForm = createElement('inputForm', 'input', 'form-input', 'submit-info')
  setAttributes(inputForm,
    'type', 'text',
    'placeholder', 'Email')
  //create a variable to store localStorage email value
  const localEmail = localStorage.getItem("Email")
  if (localStorage.getItem('Email') !== null) {
    inputForm.setAttribute('value', localEmail)
  } else {
    inputForm.setAttribute('placeholder', 'Email')
  }

  emailForm.appendChild(inputForm)

  document.querySelector('form').addEventListener('submit', function (e) {
    //create a variable to store localStorage email value
    const introducedEmail = inputForm.value;
    e.preventDefault()
    console.log(introducedEmail)
    localStorage.setItem('Email', introducedEmail)
    subscribeEmail(introducedEmail)
    sendSubscribe(introducedEmail)
    //fetch data to /subscribe endpoint
    const data = { localEmail }
    const options = {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    };
    fetch('/subscribe', options);

  })

  // const localEmail = localStorage.getItem("Email")
  // const data = { localEmail }
  // const options = {
  //   method:'POST'
  // };
  // fetch('/subscribe',options);

  const submitForm = createElement('submitForm', 'input', 'app-section__button submit-btn', 'subscribeButton')
  setAttributes(submitForm,
    'type', 'submit',
    'value', 'Subscribe')
  form.append(emailForm, submitForm)

  const isSubscribed = localStorage.getItem('isSubscribed')
  if (isSubscribed === 'true') {
    subscribe()
  } else if (isSubscribed === 'false') {
    unsubscribe()
  }
}

//functions
const createElement = (elName, htmlEl, elClass, elID) => {
  const elementName = document.createElement(htmlEl)
  elementName.className = elClass
  elementName.id = elID

  return elementName
}

const getElbyID = (elName, searchedId) => {
  const elementToSearch = document.getElementById(searchedId)

  return elementToSearch
}

const setAttributes = (elem, ...elemArguments) => {
  for (let i = 0; i < elemArguments.length; i  = 2) {
    elem.setAttribute(elemArguments[i], elemArguments[i   1])
  }
}

export const advancedSection = () => {
  addSection()
  const getHeading = document.getElementById('fourth-section')
  const sectionChildren = getHeading.children
  sectionChildren[0].innerHTML = 'Join Our Advanced Program'
  const getButton = document.getElementById('subscribeButton')
  setAttributes(getButton,
    'type', 'submit',
    'value', 'Subscribe to Advanced Program')
  getButton.className = 'app-section__button submit-btnAdvanced'
}

export default addSection

It is dinamically created and then bundeled with webpack.
Validate email function:

const VALID_EMAIL_ENDINGS = ['gmail.com', 'outlook.com', 'yandex.ru']

export const validateEmail = (email) => !!VALID_EMAIL_ENDINGS.some(v => email.includes(v))

export { VALID_EMAIL_ENDINGS as validEnding }

package.json from parent folder :

{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server",
    "lint": "eslint src"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.16.0",
    "@babel/preset-env": "^7.16.4",
    "babel-loader": "^8.2.3",
    "copy-webpack-plugin": "^6.0.0",
    "css-loader": "^6.5.1",
    "eslint": "^7.32.0",
    "eslint-config-standard": "^16.0.3",
    "eslint-plugin-import": "^2.25.3",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-promise": "^5.1.1",
    "html-webpack-plugin": "^5.5.0",
    "style-loader": "^3.3.1",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "webpack": "^5.64.2",
    "webpack-cli": "^4.9.1",
    "webpack-dev-server": "^4.5.0"
  },
  "dependencies": {
    "jquery": "^3.6.0",
    "request": "^2.79.0",
    "uglifyjs": "^2.4.11"
  }
}

webpack.config.js:

const CopyPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
var webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
    mode: 'production',
    entry: "./src/index.js",
    output: {
        filename: "main.js",
        path: path.resolve(__dirname, "dist")
    },

    optimization: {
        minimize: true,
        minimizer: [new TerserPlugin()],
    },

    performance: {
        hints: false,
        maxEntrypointSize: 512000,
        maxAssetSize: 512000
    },

    devServer: {
        hot: true,
        static: [
            {
                directory: path.join(__dirname, "dist")
            }],
        port: 9000,
        proxy: {
            '/api': 'http://localhost:3000'
        },
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /(node_modules)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            },
            {
                test: /\.css$/,
                use: [
                    { loader: 'style-loader' },
                    { loader: 'css-loader' },
                ]
            }
        ]
    },
    plugins: [
        new CopyPlugin({
            patterns: [
                { from: "src/assets/images", to: "assets/images" },
            ],
        }),
        new HtmlWebpackPlugin({
            template: 'src/index.html'
        }),
        new webpack.HotModuleReplacementPlugin(),
    ],
};

In this state that i sent to you i get the next errors:

main.js:2 POST http://localhost:9000/subscribe 404 (Not Found)  
Uncaught ReferenceError: app is not defined
    at HTMLFormElement.<anonymous> (main.js:2)  

Now some code from personal-website server:
package.json:

{
  "name": "personal-website-server",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www",
    "dev": "nodemon ./bin/www",
    "lint": "npx eslint ./",
    "lint-fix": "npx eslint ./ --fix"
  },
  "dependencies": {
    "cookie-parser": "~1.4.4",
    "debug": "~2.6.9",
    "express": "~4.16.1",
    "morgan": "~1.9.1"
  },
  "devDependencies": {
    "eslint": "^7.1.0",
    "nodemon": "^2.0.4"
  }
}

app.js:

const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');

const indexRouter = require('./routes/index');
const communityRouter = require('./routes/community');
const analyticsRouter = require('./routes/analytics');

const app = express();
global.appRoot = path.resolve(__dirname);

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/community', communityRouter);
app.use('/analytics', analyticsRouter);

module.exports = app;

www file from bin:

#!/usr/bin/env node

/**
 * Module dependencies.
 */

const app = require('../app');
const debug = require('debug')('javascript-frontend-applied-server:server');
const http = require('http');

/**
 * Get port from environment and store in Express.
 */

const port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 */

const server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', one rror);
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  const port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function one rror(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  const bind = typeof port === 'string'
    ? 'Pipe '   port
    : 'Port '   port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind   ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind   ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  const addr = server.address();
  const bind = typeof addr === 'string'
    ? 'pipe '   addr
    : 'port '   addr.port;
  debug('Listening on '   bind);
}

index.js from routes folder:

const express = require('express');
const router = express.Router();
const FileStorage = require('../services/FileStorage');

/* POST /subscribe */
router.post('/subscribe', async function (req, res) {
  try {
    if (!req.body || !req.body.email) {
      return res.status(400).json({ error: "Wrong payload" });
    }

    if (req.body.email === '[email protected]') {
      return res.status(422).json({ error: "Email is already in use" });
    }

    const data = {email: req.body.email};
    await FileStorage.writeFile('user.json', data);
    await res.json({success: true})
  } catch (e) {
    console.log(e);
    res.status(500).send('Internal error');
  }
});

/* GET /unsubscribe */
router.post('/unsubscribe ', async function (req, res) {
  try {
    await FileStorage.deleteFile('user.json');
    await FileStorage.writeFile('user-analytics.json', []);
    await FileStorage.writeFile('performance-analytics.json', []);
    await res.json({success: true})
  } catch (e) {
    console.log(e);
    res.status(500).send('Internal error');
  }
});

module.exports = router;

Let me know if you need more information,i can not get an end with this task and this drives me crazy,please help.

CodePudding user response:

I fixed the problem,it was in the webpack.config.js.I didnt listened to the apis and now it is like this :

devServer: {
        hot: true,
        open: false,
        static: [
            {
                directory: path.join(__dirname, "dist")
            }],
        port: 8080,
        proxy: [{ context: ['/community', '/subscribe', '/unsubscribe'], target: 'http://localhost:3000', }],
    },

And post ajax request:

const sendHttpRequest = (method, url, data) => {
    return fetch(url, {
        method: method,
        body: JSON.stringify(data),
        headers: data ? {
            'Content-Type': 'application/json'
        } : {}
    }).then(response => {
        if (response.status >= 400) {
            return response.json().then(errResData => {
                const error = new Error('Something went wrong!');
                error.data = errResData;
                throw error;
            });
        }
        return response.json();
    });
};

const sendData = (emailInput) => {
    sendHttpRequest('POST', 'http://localhost:8080/subscribe', {
        email: emailInput
    }).then(responseData => {
        console.log(responseData);
    }).catch(err => {
        console.log(err, err.data);
    });
}

Now when i submit an email it sends to the server and creates a user.json where the email is written.

  • Related