Arrays 异步等待JSON解析不等待
我遇到了一个问题,Arrays 异步等待JSON解析不等待,arrays,node.js,json,async-await,Arrays,Node.js,Json,Async Await,我遇到了一个问题,async/await没有等待前面的语句。我尝试读取一个JSON文件,然后尝试操作生成的对象。 尽管有一个等待,但在执行下一个函数时,数组仍然未定义 function initJson(file) { let obj; fs.readFile(file, 'utf8', (err, data) => { if (err) { throw err; } try { const obj = JSON.parse(data); con
async/await
没有等待前面的语句。我尝试读取一个JSON文件,然后尝试操作生成的对象。
尽管有一个等待
,但在执行下一个函数时,数组仍然未定义
function initJson(file) {
let obj;
fs.readFile(file, 'utf8', (err, data) => {
if (err) {
throw err;
}
try {
const obj = JSON.parse(data);
console.log(obj);
}
catch (err) {
throw err;
}
});
return obj;
};
filterItemForKeyValue = function filterItemForKeyValue(obj, k, v) {
if (typeof obj !== 'undefined' && obj) {
return obj.filter(item => item[k] !== v);
}
return false;
};
async function handleFavorites(file) {
let favorites = await initJson(file);
favorites = await filterItemForKeyValue(favorites, 'delete', true);
// here it's already false because favorites is undefined because it didn't wait
console.log(favorites);
return favorites;
};
let favs = handleFavorites('test.json');
console.log(favs);
您的
initJson
没有使用承诺,因此您不能等待响应。
通过返回如下示例所示的承诺来修改initJson
function initJson(file) {
return new Promise((resolve, reject) => {
fs.readFile(file, 'utf8', (error, data) => {
if (error) {
reject(error);
}
resolve(JSON.parse(data));
});
});
};
还为您转换了filterItemForKeyValue
:
var filterItemForKeyValue = function filterItemForKeyValue(object, key, value) {
return new Promise((resolve, reject) => {
try {
if (typeof object !== 'undefined' && object) {
resolve(object.filter(item => item[key] !== value));
}
} catch (error) {
reject(false);
}
});
};
这是您在回答中提供的更改后与结果交互的方式
handleFavorites('test.json').then((result) => {
console.log(result);
});
承诺:
异步函数:您的函数
initJson
不会作为承诺返回其结果,因此您不能等待它
该函数的核心是调用fs.readFile()
,它本身并不返回承诺。您可以通过使用util.promisify
来更改它,您的initJson
函数可以将其作为承诺返回
在您的过滤器函数上:它在调用堆栈上同步发生,不涉及异步操作,因此不需要包装为异步或返回承诺。也没有理由将其分配给变量,尤其是全局变量。只需使用函数声明,就可以了
注意,末尾的doIt
函数将对异步操作的调用包装在async关键字中。你也可以这样做,就像@Win的回答一样
最后,我修改了我的答案,以显示您将在何处处理呼叫中的错误。根据您的需要,您可能希望重新抛出错误并在等待最终结果的地方捕获它,这取决于您
附言:我强烈建议退房。它很有趣,可以帮助您更好地理解为什么有些调用是异步的,而有些则不是
const{promisify}=require('util'))
常量fs=require('fs')
const readFileAsync=promisify(fs.readFile)
异步函数initJson(文件){
const data=await readFileAsync(文件“utf8”)
返回JSON.parse(数据)
}
函数filterItemForKeyValue(对象、键、值){
if(对象类型!==“未定义”&&object){
返回object.filter(项=>项[键]!==值)
}
}
异步函数handleFavorites(文件){
试一试{
让收藏夹=等待initJson(文件)
return await filterItemForKeyValue(收藏夹,“删除”,真)
}捕捉(错误){
console.error('error',err.message)
}
}
异步函数doIt(){
const favorites=await handleFavorites('test.json')
console.log(收藏夹)
}
doIt()
谢谢,这很有道理。我还需要添加一个promise my array filter函数吗?@F.Rakes correct,如果您遇到问题,请告诉我:)我已经为您完成了上面的快速转换。还有一件事。当我试图返回我的最终值时,它被一个承诺数组(Promise{[[Object],[Object],[Object]]}
)包围着,我无法对它进行迭代。我需要先打开它吗?@F.Rakes你有没有关于如何返回最终值的示例:)就像我最初问题的最后两行一样。里面的对象是从JSON文件中正确读取的。谢谢,这也很有效,但我接受Win的回答,因为它不需要promisify
。不用担心。如果您决定使用它,它是节点标准库的一部分(我相信版本8及以上),因此它不需要安装单独的软件包。@F.Rakes我要说的一点是,将代码转换为使用所有基于承诺的语法,或所有异步和等待,可能是有意义的。这只是我的观点,但我认为选择一条路径并遵循它会降低认知开销。我最初尝试异步并等待的方式,因为它看起来更干净。如果Ipromisify
同步函数,是否有方法捕获错误?例如,您是指如何使用fs.readFile
处理错误?该调用unpromisified不是同步的,而是将其结果传递给回调处理程序,正如您在原始问题中所写的那样。我将修改答案以显示错误处理。