Search code examples
javascriptfetch

Prevent submit button from firing multiple fetch requests


I have a section on a webpage for a task :
enter image description here

In the form i write an email which is 'validated' later with a function.First when i submit an email which passed the validation it sends a sendSubscribe function to the server,after that i click the button unsubscribe and it sends a unsubscribeUser function.But,after that,when i click on the email input,it starts to send unsubscribe fetch requests everytime and when i click on the subscribe button it also does the same.
The network tab looks like this:
enter image description here

I think i know which is the problem,but i dont know how to fix it.My idea is that everytime i click on the subscribe button it ataches an event listener from the function,thats why it fires multiple unsubscribe requests.

Subscribe functions : the subscribeEmail is the most important

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

export const subscribe = () => {
  const subscribeBtn = document.getElementById('subscribeButton')
  subscribeBtn.setAttribute('value', 'Unsubscribe')
  document.getElementById('emailForm').style.display = 'none'
  localStorage.setItem('isSubscribed', 'true')
  document.getElementById('submit-info').value = ''
}

export const unsubscribe = () => {
  const subscribeBtn = document.getElementById('subscribeButton')
  subscribeBtn.setAttribute('value', 'Subscribe')
  document.getElementById('emailForm').style.display = 'block'
  localStorage.setItem('isSubscribed', 'false')
}

export const subscribeEmail = (email) => {
  const isValidEmail = validateEmail(email)
  if (isValidEmail === true) {
    subscribe()
    document.querySelector('form').addEventListener('click', function (e) {
      unsubscribe()
      unsubscribeUser()
      localStorage.removeItem('Email')
      e.stopPropagation()
    })
  } else if (isValidEmail === false) {
    unsubscribe()
  }
}  

Subscribe fetch functions:

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)
  })
}

Unsubscribe fetch function:

export const unsubscribeUser = () => {
  fetch('http://localhost:8080/unsubscribe', { method: 'POST' }).then(response => { console.log(response.status) })
}

Subscribe button event listener:

document.querySelector('form').addEventListener('submit', async 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)   //change the button style and set in local storage isSubscribed to true
    sendSubscribe(introducedEmail)  //send subscribe fetch to the server

    // prevent additional requests upon clicking on "Subscribe" and "Unsubscribe".
    if (isFetching) return // do nothing if request already made
    isFetching = true
    disableBtn()
    const response = await fetchMock()  //eslint-disable-line
    isFetching = false
    enableBtn()
  })  

// functions for disabling the submit button when a fetch request is in progress

const fetchMock = () => {
    return new Promise(resolve => setTimeout(() => resolve('hello'), 2000))
  }

  const disableBtn = () => {
    submitForm.setAttribute('disabled', 'disabled')
    submitForm.style.opacity = '0.5'
  }
  const enableBtn = () => {
    submitForm.removeAttribute('disabled')
    submitForm.style.opacity = '1'
  }
}

Could you guys please help me? I have no idea how to fix this.Thanks in advance!


Solution

  • So,like i said,the problem was in the function that attached a new event listener to the button,thats why unsubscribe request was sent everytime with +1 more request. So,i did this way :
    Function for the submit button:

    let isUsed = false
    
      const submitClickButton = async () => {
        // create a variable to store localStorage email value
        const introducedEmail = inputForm.value
        //e.preventDefault()
        console.log(introducedEmail)
        localStorage.setItem('Email', introducedEmail)
        subscribeEmail(introducedEmail)   //change the button style and set in local storage isSubscribed to true
        sendSubscribe(introducedEmail)  //send subscribe fetch to the server
    
        // prevent additional requests upon clicking on "Subscribe" and "Unsubscribe".
        if (isFetching) return // do nothing if request already made
        isFetching = true
        disableBtn()
        const response = await fetchMock()  //eslint-disable-line
        isFetching = false
        enableBtn()
    
        isUsed = true
      }
    
      const undoClickButton = () => {
        //e.preventDefault()
        //unsubscribeEmail()
        unsubscribeEmail()
    
        isUsed = false
      }
    
      const toggleButton = () => {
        isUsed ? undoClickButton() : submitClickButton()
      }
    
      submitForm.addEventListener('click', toggleButton, false)  
    

    And subscribeEmail function :

    export const subscribeEmail = (email) => {
      const isValidEmail = validateEmail(email)
      if (isValidEmail === true) {
        subscribe()
        // document.querySelector('form').addEventListener('click', function (e) {
        //   unsubscribe()
        //   unsubscribeUser()
        //   localStorage.removeItem('Email')
        //   e.stopPropagation()
        // })
      } else if (isValidEmail === false) {
        unsubscribe()
      }
    }
    
    export const unsubscribeEmail = () => {
     // const isValidEmail = validateEmail(email)
    // if (isValidEmail===true){
        unsubscribe()
        unsubscribeUser()
        localStorage.removeItem('Email')
      //}
    }