Javascript 读入并解析后从JSON文件返回随机值

Javascript 读入并解析后从JSON文件返回随机值,javascript,node.js,Javascript,Node.js,在读入并解析后,我试图从JSON文件返回一个随机值。当我尝试使用返回时,我得到了一个未定义的错误,但是可以通过控制台输出该值。有什么好办法处理这个问题吗 const fs = require('fs'); function getRandFact() { fs.readFile('facts.json', (err, data) => { if (err) throw err; const obj = JSON.parse(data);

在读入并解析后,我试图从JSON文件返回一个随机值。当我尝试使用返回时,我得到了一个未定义的错误,但是可以通过控制台输出该值。有什么好办法处理这个问题吗

const fs = require('fs');

function getRandFact() { 
    fs.readFile('facts.json', (err, data) => {
        if (err) throw err;
        const obj = JSON.parse(data);
        const keys = Object.keys(obj);
        const randIndex = Math.floor(Math.random() * keys.length);
        const randKey = keys[randIndex];
        const randVal = obj[randKey];
        console.log(randVal);
        return randVal;
    });
}

console.log(getRandFact());

您正在处理的代码正在异步运行。日志记录发生在
getRandFact()
返回值之后,即它实际收到值时。在异步回调中返回值没有帮助-它在不同的范围内返回值。错误也是如此:如果有错误,它会把它扔到无法处理的地方

在这种情况下,您至少有两种选择:

  • 提供对
    getRandFact()
    的回调以使用它

    function getRandFact(doSomethingWithRandFact) { 
        fs.readFile('facts.json', (err, data) => {
            if (err) return doSomethingWithRandFact(err);
            // ... all your  other stuff
            console.log(randVal);
            return doSomethingWithRandFact(null, randVal);
        });
    }
    
    getRandFact((err, fact) => {
      if (err) {
        return console.error("Something happened while reading facts.json:", err);
      }
      console.log(fact);
    });
    
  • getRandFact()
    转换为一个返回
    Promise
    的函数,并使用该函数:

    function getRandFact() { 
      return new Promise((resolve, reject) => {
        fs.readFile('facts.json', (err, data) => {
          if (err) return reject(err);
          // ... all your other stuff
          console.log(randVal);
          return resolve(randVal);
        });
      });
    }
    
    getRandFact()
      .then(fact => console.log(fact));
      .catch(err => console.error("Something happened getting the random fact:", err));
    

  • 我建议选择2,因为传递回调会很快导致“回调地狱”,错误处理也有点棘手。

    你把异步代码和同步代码混淆了

    您必须了解异步代码的工作原理:

    回调:

    最后,在您学习了一点异步和使用回调之后,下面是一个解释

    const fs = require('fs');
    
    function getRandFact() { 
        fs.readFile('facts.json', (err, data) => {
            if (err) throw err;
            const obj = JSON.parse(data);
            const keys = Object.keys(obj);
            const randIndex = Math.floor(Math.random() * keys.length);
            const randKey = keys[randIndex];
            const randVal = obj[randKey];
            console.log(randVal);
            return randVal;
        });
    }
    
    console.log(getRandFact());
    
    一旦调用getRandFact(),就会调用fs.readFile函数,该函数会在内部开始处理文件(基本上可以说它正在读取,并且该读取是异步的,因此需要时间),但是
    getRandFact
    函数返回
    未定义的
    。
    因此,控制台日志打印未定义。
    然后在稍后的某个时间点,fs的读取完成,然后调用回调函数viz
    (err,data)=>{}
    带有参数,以便现在可以使用它们

    因此,要解决此问题,您必须执行以下操作:

    const fs = require('fs');
    
    function getRandFact(callback) { 
        fs.readFile('facts.json', (err, data) => {
            if (err) throw err;
            const obj = JSON.parse(data);
            const keys = Object.keys(obj);
            const randIndex = Math.floor(Math.random() * keys.length);
            const randKey = keys[randIndex];
            const randVal = obj[randKey];
            console.log(randVal);
            callback(randVal); // Notice that we called the callback function
            // function and passed the random value as the parameter to it
        });
    }
    
    // This will be called with the randomValue that 
    // will be generated and then you can use that value
    function callback (randomValue) {
      console.log(randomValue);
    }
    
    // We're passing the callback function
    // as an argument to the getRandFact function
    getRandFact(callback);
    
    可能重复的