Node.js JsonParser 自定义函数“无法读取未定义的属性”

Posted

技术标签:

【中文标题】Node.js JsonParser 自定义函数“无法读取未定义的属性”【英文标题】:Node.js JsonParser custom function "cannot read property of undefined" 【发布时间】:2021-02-27 07:07:03 【问题描述】:

我正在尝试创建一个 JSON 函数,该函数将能够从 JSON 文件中为多个其他函数返回解析的数据,而无需一遍又一遍地重写相同的代码。这是我拥有的函数以及一个变量:

var fs = require('fs');
function jsonParser(jsonFile) 
    fs.readFile(jsonFile,
        function (err, data) 
            var jsonData = data;
            var jsonParsed = JSON.parse(jsonData);
            return jsonParsed;
        )
;

当我将console.log 插入此函数进行测试时,它会毫无问题地从jsonParsed 返回数据。以下是如何使用此函数的一个示例:

msg.channel.send(jsonParser('package.json').version);

这是从中加载的 JSON 文件:


  "name": "discord-bot",
  "version": "0.4.0",
  "description": "Mírre from The Autorise Domain recreated as a Discord bot",
  "main": "index.js",
  "scripts": 
    "test": "echo \"Error: no test specified\" && exit 1"
  

我尝试了多种方法来尝试获取“版本”数据,但它每次都返回相同的“无法读取未定义的'版本'的属性”消息。我希望能够通过msg.channel.send() 推送对象数据,但这并没有发生——就好像程序在对象到达发送函数时已经从内存中擦除了对象一样。

任何帮助将不胜感激!

编辑: 该函数在Discord.Client() 消息函数中被调用。在将机器人定义为const bot = new Discord.Client() 后,使用jsonParser 的命令从一个大的bot.on('message'... 函数中调用。从这里开始,有人可以给机器人提供多个命令的切换案例,其中一个用于查找机器人的版本;这是调用jsonParser 的地方。

【问题讨论】:

您实际上并没有从您的函数中返回 json。您从 readFile 的回调中返回它,但您没有从父函数返回,因此您将继续获得未定义,直到您从父函数返回。 因为你使用回调来读取文件,你应该使用promises来代替:fs.promises.readfile(jsonFile)msg.channel.send((await jsonParser('package.json')).version); @HoangDao 似乎走在正确的轨道上,但并非完全正确。现在我被告知 SyntaxError: Unexpected identifier 用于 msg 行中的 jsonParser。 这个错误看起来很奇怪,你是不是遗漏了什么? @Freerey 啊,我想你的 json 文件末尾缺少 【参考方案1】:

正如我所说,更改为 fs.promises 没有问题:

const fs = require('fs');
const path = require('path');

async function jsonParser(jsonFile) 
  const data = await fs.promises.readFile(path.resolve(__dirname, jsonFile));

  var jsonData = data.toString('utf-8');
  var jsonParsed = JSON.parse(jsonData);
  return jsonParsed;
;

(async function (jsonFile) 
  const data = await jsonParser(jsonFile);
  console.log(data.version);
)('./test.json').catch(e => 
  console.log(e);
);

由于此代码用于 Discord 机器人,因此请确保客户端的 .on 函数使用 async(),如下所示:

const bot = new Discord.Client();
...
bot.on('message', async(msg) => ...

【讨论】:

同步/异步函数之间似乎存在某种差异。当我将async function (jsonFile) 部分放在括号中时,我没有得到任何数据,调试器也没有显示任何错误,但只是将这些代码行放入内部而不包装在异步函数中会导致错误await is only valid in async function 出现.为了帮助更好地理解这是什么类型的函数,我将用更多代码更新这个问题。 你在函数中缺少async 声明,如果你使用不和谐,它应该类似于bot.on('message', async () => <your logic of await reading jsonParser will be here>); 非常感谢您的帮助!我稍微编辑了答案,以阐明这将如何在 Discord 机器人上运行,现在它运行良好。 :)【参考方案2】:

如果在执行期间 JSON 中没有任何变化(在 package.json 的情况下不应该发生这种情况),您可以继续使用 require。

const  version  = require('./package.json');

...

msg.channel.send(version);

【讨论】:

以上是关于Node.js JsonParser 自定义函数“无法读取未定义的属性”的主要内容,如果未能解决你的问题,请参考以下文章

JSPug调用自定义JS函数

Node.js插件编写-导出类对象作为参数传递

Node.js插件编写-导出类对象作为参数传递

Node.js插件编写-导出类对象作为参数传递

更正 node.js 中的异步函数导出

如何在 Sequelize 中的导入模型中创建自定义方法或函数