我对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']
答案 0 :(得分:2)
由于您是JS的新手,所以只需进一步迭代Tyler的答案即可。自从JavaScript异步以来,JavaScript就严重依赖于回调或Promise。这意味着您阅读代码的顺序不是(总是)代码执行的顺序。
您的代码如下:
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", {});
//loggin here returns correct
但是它将按以下顺序执行:
//loggin here returns empty
//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)
})
})