Home > Net >  Unsubscribe email using Fetch api Javascript
Unsubscribe email using Fetch api Javascript

Time:12-20

I have a form where i enter an email and it gets ''subscribed'' in a user.json file using a fetch api on node server.My task is to :

  • upon clicking on the "Unsubscribe" button, implement the functionality for unsubscribing from the community list. For that, make POST Ajax request using http://localhost:3000/unsubscribe endpoint.

I tried to make the function but it wasnt succeseful so i deleted it. Also,i need to do the following :

  • While the requests to http://localhost:3000/subscribe and http://localhost:3000/unsubscribe endpoints are in progress, prevent additional requests upon clicking on "Subscribe" and "Unsubscribe". Also, disable them (use the disabled attribute) and style them using opacity: 0.5.
    For me ajax requests,fetch and javascript is something new,so i dont know really well how to do this task,if you could help me i'll be happy,thanks in advance.

fetch code for subscribing:

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

export const sendSubscribe = (emailInput) => {
    const isValidEmail = validateEmail(emailInput)
    if (isValidEmail === true) {
        sendData(emailInput);
    }
}

export 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 => {
        return responseData
    }).catch(err => {
        console.log(err, err.data);
        window.alert(err.data.error)
    });
}

index.js from route node server:

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;

And user.json file looks like this :

{"email":"[email protected]"}

This is my attempt for unsubscribing :

export const unsubscribeUser = () => {
    try {
        const response =  fetch('http://localhost:8080/unsubscribe', {
          method: "POST"
        });
      
        if (!response.ok) {
          const message = 'Error with Status Code: '   response.status;
          throw new Error(message);
        }
      
        const data =  response.json();
        console.log(data);
      } catch (error) {
        console.log('Error: '   error);
      }
}

It gives the following errors:

Error: Error: Error with Status Code: undefined
main.js:2 
main.js:2 POST http://localhost:8080/unsubscribe 404 (Not Found)

FileStorage.js:

const fs = require('fs');
const fsp = fs.promises;

class FileStorage {
  static getRealPath(path) {
    return `${global.appRoot}/storage/${path}`
  }

  static async checkFileExist(path, mode = fs.constants.F_OK) {
    try {
      await fsp.access(FileStorage.getRealPath(path), mode);
      return true
    } catch (e) {
      return false
    }
  }

  static async readFile(path) {
    if (await FileStorage.checkFileExist(path)) {
      return await fsp.readFile(FileStorage.getRealPath(path), 'utf-8');
    } else {
      throw new Error('File read error');
    }
  }

  static async readJsonFile(path) {
    const rawJson = await FileStorage.readFile(path);
    try {
      return JSON.parse(rawJson);
    } catch (e) {
      return {error: 'Non valid JSON in file content'};
    }
  }

  static async writeFile(path, content) {
    const preparedContent = typeof content !== 'string' && typeof content === 'object' ? JSON.stringify(content) : content;
    return await fsp.writeFile(FileStorage.getRealPath(path), preparedContent);
  }

  static async deleteFile(path) {
    if (!await FileStorage.checkFileExist(path, fs.constants.F_OK | fs.constants.W_OK)) {
      return await fsp.unlink(FileStorage.getRealPath(path));
    }
    return true;
  }

}

module.exports = FileStorage;

CodePudding user response:

You should consider using a database for handling CRUD operations on your persisted data. If you must use filestorage, theres a flat file DB library called lowdb that can make working the files easier.

As for preventing duplicate requests, you can track if user has already made a request.

let fetchBtn = document.getElementById('fetch')
let isFetching = false

fetchBtn.addEventListener('click', handleClick)

async function handleClick(){
  if (isFetching) return // do nothing if request already made
  isFetching = true
  disableBtn()
  const response = await fetchMock()
  isFetching = false
  enableBtn()
}

function fetchMock(){
    // const response = await fetch("https://example.com");
  return new Promise(resolve => setTimeout (() => resolve('hello'), 2000))
}

function disableBtn(){
  fetchBtn.setAttribute('disabled', 'disabled');
  fetchBtn.style.opacity = "0.5"
}
function enableBtn(){
  fetchBtn.removeAttribute('disabled');
  fetchBtn.style.opacity = "1"
}
<button type="button" id="fetch">Fetch</button>

  • Related