Express / Node.js |从全局调用中生成新的JSON对象

时间:2018-08-20 20:36:43

标签: javascript node.js express glob

我对JS还是很陌生,我想我缺少关于对象状态存储和嵌套函数调用结构的一些基本知识。

我正在遍历包含许多JSON文件的目录,并且我想迭代地加载这些文件并将内容解析为单个JSON对象。 我在函数内部正确解析了内容,但是正如我写的那样,对象状态并没有在函数外部持久存在。

const glob = require('glob');

const retrieve = (query) => {
    const dataJSON = {};
    const json_path = saveDir + '/upload/' + query + '/'
    glob(json_path + '*.json', function (er, files) {
        for (index in files) {
            dataJSON[index] = require(files[index])
        }
        // Logging here returns the correct object
        console.log(dataJSON)
        return dataJSON
    });
    // Logging here returns an empty object
    console.log(dataJSON)
    return dataJSON

}

// I need to return the object here
app.get('/patent', (req, res) => {
    res.json(retrieve(req.query['q']))
});

两个问题,我该如何在glob之外持久存储“ dataJSON”,以及如何从glob外部返回“文件”?

例如第二个问题

var example = glob("**/*.js", function (er, files) {
  // files is an array of filenames.

  return files
})

console.log(example)
>>['file1.json', 'file2.json', 'file3.json']

2 个答案:

答案 0 :(得分:2)

由于您是JS的新手,所以只需进一步迭代Tyler的答案即可。自从JavaScript异步以来,JavaScript就严重依赖于回调或Promise。这意味着您阅读代码的顺序不是(总是)代码执行的顺序。

您的代码如下:

  1. 定义函数检索
  2. 定义一些变量
  3. 调用glob读取一些文件
  4. 使用这些文件function add(num1, num2){ if(typeof num1!=="number"||typeof num2!=="number"){ throw new TypeError("You must provide numbers!"); } return num1+num2; } console.log(add(1,2)); add("string", {});
  5. 返回dataJSON结果//loggin here returns correct

但是它将按以下顺序执行:

  1. 定义函数检索
  2. 定义一些变量
  3. 调用glob读取一些文件
  4. 返回dataJSON结果//loggin here returns empty
  5. 使用这些文件//loggin here returns empty

原因是该glob调用花费了一些时间(列表中的nr 3)。可能只有几毫秒,但是您的代码仍在继续运行。因此,当glob读取这些文件时,您的程序仍然运行。 glob完成后,它将运行回调函数。

回调基本上是“嘿,当您阅读这些文件,然后对它们进行处理”

因此,当您执行console.log时,您没有对文件做任何事情。 Glob仍在工作。

您几乎看不到console.logs。

//loggin here returns correct

所以您会认为输出将是:

const retrieve = (query) => {
    console.log('STEP 1')
    const dataJSON = {};
    const json_path = saveDir + '/upload/' + query + '/'
    glob(json_path + '*.json', function (er, files) {
        for (index in files) {
            dataJSON[index] = require(files[index])
        }
        // Logging here returns the correct object
        console.log('STEP 2')
        return dataJSON
    });
    console.log('STEP 3')
    // Logging here returns an empty object
    console.log(dataJSON)
    return dataJSON
}

但它将是:

STEP 1
STEP 2
STEP 3

提到了类似泰勒的几种方法来解决此问题。

您可以继续进行回调。

STEP 1
STEP 3
STEP 2

请注意,我在检索函数中添加了一个新参数。那是回调,以便我们知道glob完成的时间。现在,我可以在路由器中使用该回调了。

另一种方法是使用诺言。

这是泰勒建议的方法,我同意。我个人更喜欢promise,而不是回调。

const glob = require('glob');

const retrieve = (query, cb) => {
    const dataJSON = {};
    const json_path = saveDir + '/upload/' + query + '/'
    glob(json_path + '*.json', function (er, files) {
        for (index in files) {
            dataJSON[index] = require(files[index])
        }
        // Logging here returns the correct object
        console.log(dataJSON)
        cb(dataJSON)
    });
}

app.get('/patent', (req, res) => {
  retrieve(req.query['q'], function(resultsFromGlob) {
    res.json(resultsFromGlob) 
  })
});

这也使我可以选择使用异步/等待

const retrieve = (query) => {
    return new Promise((resolve,reject) => {
      const dataJSON = {};
      const json_path = saveDir + '/upload/' + query + '/'
      glob(json_path + '*.json', function (er, files) {
          if (error) {
            reject(error)
          }

          for (index in files) {
              dataJSON[index] = require(files[index])
          }

          resolve(dataJSON);
      });
    })
}

app.get('/patent', (req, res) => {
  retrieve(req.query['q']).then(resultsFromGlob => {
    res.json(resultsFromGlob) 
  })  
});

答案 1 :(得分:1)

glob看起来是异步的(因此,回调/ dataJson是一个空对象)。您有两种选择:

承诺化

function retrieve (query) {
  return new Promise(function (resolve, reject) {
    glob(json_path + "*.json", function (err, files) {
      if (err) reject(files)
      else resolve(files)
    })
  })
}

app.get("/patent", (req, res) => {
  retrieve(req.query["q"])).then(files => res.json(files))
})

或只是内联并在回调中返回您的回复

app.get("/patent", (req, res) => {
  glob(json_path + "*.json", function (err, files) {
    res.json(files)
  })
})