我遇到async/await
不等待上一条语句的问题。我正在尝试读取JSON文件,然后尝试操纵结果对象。
尽管有await
,但在执行下一个功能时,该数组仍未定义。
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);
答案 0 :(得分:4)
您的initJson
没有使用Promise,因此您无法等待响应。
通过返回如下所示的承诺来修订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);
});
承诺:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
异步功能:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
答案 1 :(得分:2)
您的函数initJson
不会将其结果作为承诺返回,因此您无法await
。
该函数的核心是对fs.readFile()
的调用,该调用本身不会返回promise。您可以使用util.promisify
进行更改,而initJson
函数可以将其作为承诺返回。
在您的过滤器函数上:它是在调用堆栈上同步发生的,并且不涉及异步操作,因此不需要不需要包装在异步中或返回promise。也没有理由将其分配给变量,尤其是没有全局变量。只需使用函数声明,这就是您所需要的。
请注意,最后的doIt
函数将对异步操作的调用包装在async关键字中。您也可以这样做,就像@Win的答案一样。
最后,我修改了答案,以显示您将在呼叫中处理错误的位置。根据您的需要,您可能希望重新抛出该错误并在等待最终结果的地方捕获该错误,这取决于您。
PS:我强烈建议您检出this video on call stack vs event loop in JavaScript。这很有趣,可以帮助您更好地理解为什么有些电话不同步的原因。
const {promisify} = require('util')
const fs = require('fs')
const readFileAsync = promisify(fs.readFile)
async function initJson(file) {
const data = await readFileAsync(file, 'utf8')
return JSON.parse(data)
}
function filterItemForKeyValue(object, key, value) {
if (typeof object !== 'undefined' && object) {
return object.filter(item => item[key] !== value)
}
}
async function handleFavorites(file) {
try {
let favorites = await initJson(file)
return await filterItemForKeyValue(favorites, 'delete', true)
} catch (err) {
console.error('error', err.message)
}
}
async function doIt(){
const favorites = await handleFavorites('test.json')
console.log(favorites)
}
doIt()