NODE.JS 如何在不填满存储空间的情况下保存 JSON 数据 [关闭]

Posted

技术标签:

【中文标题】NODE.JS 如何在不填满存储空间的情况下保存 JSON 数据 [关闭]【英文标题】:NODE.JS How do I save JSON data without filling up my storage [closed] 【发布时间】:2021-08-07 17:27:21 【问题描述】:

标题确实说明了这一点。

我制作了一个不和谐机器人,并添加了一个排名系统,该系统在我的文件系统中存储了它的内存。但是,如果加入的人太多,我的存储空间就会被填满。也许我有办法访问 node.js 服务器?也许本地主机?我只想要免费保存数据的任何东西,不由我以外的任何人管理,并且不占用我的存储空间

【问题讨论】:

您能否扩展一下您正在做的事情并为您的问题提供更多背景信息?目前,这个问题听起来有点像XY problem。也许您正在寻找database。 idownvotedbecau.se/unclearquestion 所以只需在本地机器上运行任何数据库) @NikitaMazur 任何在 OP 机器上运行的数据库也会耗尽它们宝贵的有限存储空间。 @MrMythical 是的,您只需让机器人写入该驱动器上的文件(或设置使用该驱动器作为存储的数据库)。快速测试意味着 10 000 个用户将占用您的架构将占用大约 700 KB 的磁盘空间,即每个用户大约 70 个字节。使用 399 GB,您可以存储大约 5 700 000 000 个用户。 【参考方案1】:

配置

对于这个答案,我们将建立一个简单的 config 对象来存储任何值 -

// config.json

"counter":0

服务器

我们将使用http.createServer 创建一个简单的服务器。我们将使用请求方法和请求 URL 来查找 handler 或在未找到处理程序时以 404 响应 -

// server.js

import  createServer  from "http"
import  readFile, writeFile  from "fs/promises"

const server = createServer(async (req, res) => 
  const handler = routes?.[req.method.toLowerCase()]?.[req.url]
  if (handler == null) 
    res.writeHead(404, 'Content-Type': 'text/plain')
    res.end(`No route for $req.method $req.url`)
  
  else 
    await handler(req, res)
    res.end()
  
)

server.listen(8000)

接下来我们将routes 定义为/getConfig/saveConfig -

// server.js (continued)

const routes = 
  get: 
    "/getConfig": async (req, res) => 
      res.writeHead(200, 'content-type': 'application/json')
      res.write(await readFile("./config.json"))
    
  ,
  post: 
    "/saveConfig": async (req, res) => 
      await writeFile("./config.json", await readBody(req))
      res.writeHead(204)
    ,
    "/reset": async (req, res) => 
      await writeFile("./config.json", JSON.stringify( counter: 0 ))
      res.writeHead(204)
    
  

这取决于一个可重用的助手,readBody -

// server.js (continued)

function readBody(req) 
  return new Promise((resolve, reject) => 
    const body = []
    req.on('data', chunk => body.push(Buffer.from(chunk)))
    req.on('end', _ => resolve(Buffer.concat(body).toString()))
    req.on('error', reject)
  )

客户

在这种情况下,您的机器人是 http 客户端。 http.get 的节点文档包含这个冗长的示例,但不要让您担心 -

// example from node docs

http.get('http://localhost:8000/', (res) => 
  const  statusCode  = res;
  const contentType = res.headers['content-type'];

  let error;
  // Any 2xx status code signals a successful response but
  // here we're only checking for 200.
  if (statusCode !== 200) 
    error = new Error('Request Failed.\n' +
                      `Status Code: $statusCode`);
   else if (!/^application\/json/.test(contentType)) 
    error = new Error('Invalid content-type.\n' +
                      `Expected application/json but received $contentType`);
  
  if (error) 
    console.error(error.message);
    // Consume response data to free up memory
    res.resume();
    return;
  

  res.setEncoding('utf8');
  let rawData = '';
  res.on('data', (chunk) =>  rawData += chunk; );
  res.on('end', () => 
    try 
      const parsedData = JSON.parse(rawData);
      console.log(parsedData);
     catch (e) 
      console.error(e.message);
    
  );
).on('error', (e) => 
  console.error(`Got error: $e.message`);
);

您不应逐字复制此内容。想象一下,每次您想获取一些 JSON 时都要编写那么多代码。您可以将http 模块视为一个低级 API,使您能够设计更高级别的函数 -

// client.js 

import * as http from "http"

function request (href,  body = "", ...options  = ) 
  return new Promise((resolve, reject) =>
    http.request(href, options, res => 
      const data = []
      res.on('data', chunk => data.push(chunk))
      res.on('end', _ => resolve(
        status: res.statusCode,
        headers: res.headers,
        data: Buffer.concat(data).toString()
      ))
    )
    .on('error', reject)
    .end(body)
  )

在我们的request 函数之上解析一个 status, headers, data 对象,我们可以编写专门的表单getgetJson,使其更容易与 -

// client.js (continued)

async function get (href) 
  const  status, headers, data  = await request(href)
  if (status < 200 || status >= 300)
    throw Error(status)
  return  status, headers, data 


async function getJson (href) 
  const  headers, data  = await get(href)
  if (!headers['content-type'].startsWith("application/json"))
    throw Error(`expected application/json but received $headers['content-type']`)
  return JSON.parse(data)

我们可以为post 做同样的事情-

// client.js (continued)

async function post (href, body = "") 
  const  status, headers, data  = await request(href,  body, method: "POST" )
  if (status < 200 || status >= 300)
    throw Error(status)
  return  status, headers, data 

最后是我们的bot 代码。它通过get读取配置,通过post更新配置,并通过get重新读取配置返回确认结果-

// client.js (continued)

async function bot() 
  const config = await getJson("http://localhost:8000/getConfig")
  await post("http://localhost:8000/saveConfig", JSON.stringify(counter: config.counter + 1))
  return getJson("http://localhost:8000/getConfig")


bot().then(console.log, console.error)

运行

在终端中启动server -

$ node ./server.js

单独的终端中,运行几次client -

$ node ./client.js
 counter: 1 
$ node ./client.js
 counter: 2 
$ node ./client.js
 counter: 3 

节点模块

在上面,我们采取了一种 DIY 方法来解决这个问题。但是这种问题之前已经解决了很多方法。有一些流行的库,如 express 和 koajs,这将使这一切变得容易得多。既然您知道它们的用途,那就试试吧!

【讨论】:

【参考方案2】:

只需使用数据库,mongoDB atlas 就可以很好地满足您的需求,因为它是基于云的并且非常易于设置。您可以按照此tutorial 将您的 discord 机器人与 mongoDB atlas 连接起来。

【讨论】:

以上是关于NODE.JS 如何在不填满存储空间的情况下保存 JSON 数据 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Node.js:如何在不上传文件列表的情况下检查文件夹是不是为空

如何在不使用 npm 的情况下安装 node.js 模块?

如何在不重新加载页面的情况下将任意 JSON 发送到 node.js?

是否可以在不调用“节点”的情况下运行 Node.js 脚本?

如何在 Ubuntu 上停止 Node.js 并在不停止的情况下注销 [重复]

如何在不使用 node.js 的情况下添加标准反应应用程序 [关闭]