使用 Fetch api Javascript 取消订阅电子邮件

Posted

技术标签:

【中文标题】使用 Fetch api Javascript 取消订阅电子邮件【英文标题】:Unsubscribe email using Fetch api Javascript 【发布时间】:2022-01-21 18:39:23 【问题描述】:

我有一个表单,我在其中输入电子邮件,它使用节点服务器上的 fetch api 在 user.json 文件中“订阅”。我的任务是:

点击“退订”按钮后,实现退订社区列表的功能。为此,请使用 http://localhost:3000/unsubscribe 端点发出 POST Ajax 请求。

我尝试创建该功能,但没有成功,因此我将其删除。另外,我需要执行以下操作:

同时请求 http://localhost:3000/subscribe 和 http://localhost:3000/unsubscribe 端点正在进行中,防止 单击“订阅”和“取消订阅”后的其他请求。 此外,禁用它们(使用 disabled 属性)并使用 不透明度:0.5。 对我来说,ajax 请求、fetch 和 javascript 是新事物,所以我不太清楚如何完成这项任务,如果你能帮助我,我会很高兴,提前谢谢。

获取订阅代码:

 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:

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 === 'forbidden@gmail.com') 
      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;

user.json 文件看起来像这样:

"email":"Email@gmail.com"

这是我退订的尝试:

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

它给出了以下错误:

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;

【问题讨论】:

我觉得这并不难,但是网上关于这方面的信息并不多.. 404 资源未找到意味着端点无法访问。如果您的代码更改未自动更新,请尝试重新启动服务器。还要确保您的端口号匹配。 我重新启动了服务器,检查了数字,一切都很好,我不明白为什么它不想发出这个帖子请求.. 我没有发现任何明显的问题,请尝试重用您用来发出订阅请求的相同功能。 sendHttpRequest('POST', 'http://localhost:8080/subscribe')。一般来说,尝试复制您使用订阅所做的每一件小事。 Wooooooooooooooooooooow,路线出错,额外的空间... router.post('/unsubscribe ', 【参考方案1】:

您应该考虑使用数据库来处理对持久数据的 CRUD 操作。如果您必须使用文件存储,则有一个名为 lowdb 的平面文件数据库库可以使处理文件更容易。

关于防止重复请求,您可以跟踪用户是否已经发出请求。

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>

【讨论】:

任务是掌握ajax请求并使用这个节点服务器,我不能使用其他任何东西:( 太糟糕了,你的 Filestorage.js 服务文件是什么样的。 我在问题中添加了 我在答案中添加了禁用按钮的代码。 谢谢!我尝试让这篇文章取消订阅,然后我尝试按钮 的代码

以上是关于使用 Fetch api Javascript 取消订阅电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

html 如何使用JavaScript Fetch API

javascript 使用fetch API的简单POST请求

Javascript fetch api:无法检索某些响应标头

使用 javascript fetch api 执行 POST 请求

如何使用“Fetch API”在 javascript 和 c# 之间传递数据?

使用 Javascript Fetch API 发送的快速解析文件