防止提交按钮触发多个获取请求

Prevent submit button from firing multiple fetch requests

我在网页上有一个部分用于任务:

在表单中我写了一封电子邮件 'validated' 后来 function.First 当我提交一封通过验证的电子邮件时它会向服务器发送一个 sendSubscribe 函数,之后我点击取消订阅按钮,它发送一个取消订阅用户 function.But,之后,当我点击电子邮件输入时,它开始发送取消订阅提取请求,当我点击订阅按钮时,它也做同样的事情。
网络选项卡如下所示:

我想我知道问题出在哪里,但我不知道如何解决 it.My 我的想法是,每次我单击订阅按钮时,它都会从函数中附加一个事件侦听器,这就是它触发多个事件的原因取消订阅请求。

订阅功能:订阅邮箱最重要

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

订阅获取函数:

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

退订获取功能:

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

订阅按钮事件监听器:

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

// 用于在获取请求正在进行时禁用提交按钮的函数

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

你们能帮帮我吗?我不知道如何提前修复this.Thanks!

我修改了你所有的功能并解决了你的问题,实现了async和await。

https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await

订阅获取函数

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

export const sendSubscribe = async (emailInput) => {
    const isValidEmail = validateEmail(emailInput) // idk if this is async func
    if (isValidEmail === true) {
        await sendData(emailInput);
    }
}

export const sendHttpRequest = async (method, url, data) => {
  return await 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 = async (emailInput) => {
  await sendHttpRequest('POST', 'http://localhost:8080/subscribe', {
    email: emailInput
  }).then(responseData => {
    return responseData
  }).catch(err => {
    console.log(err, err.data)
    window.alert(err.data.error)
  })
}

退订获取功能

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

订阅按钮事件监听器

let isFetching = false;

document.querySelector('form').addEventListener('submit', async function (e) {
    e.preventDefault();
    if (isFetching) return // do nothing if request already made

    // create a variable to store localStorage email value
    const introducedEmail = inputForm.value;
    
    console.log(introducedEmail);

    localStorage.setItem('Email', introducedEmail);

    // prevent additional requests upon clicking on "Subscribe" and "Unsubscribe".
    disableBtn();
    await fetchMock();
    isFetching = true;

    await subscribeEmail(introducedEmail);   //change the button style and set in local storage isSubscribed to true
    await sendSubscribe(introducedEmail);  //send subscribe fetch to the server

    // data sent, reenabling button    
    isFetching = true
    enableBtn();
});

// 用于在获取请求正在进行时禁用提交按钮的函数

...
    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'
    }
}

所以,就像我说的,问题出在将新事件侦听器附加到按钮的函数中,这就是为什么每次发送取消订阅请求时都会再发送 +1 个请求。所以,我这样做了:
提交按钮的功能:

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)  

和订阅电子邮件功能:

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