javascript - 我制作了一个 JavaScript 对象,我无法从中进行迭代,甚至无法访问它的参数。我错过了什么?
问题描述
这是我在 Chrome 中登录时的对象:
{}
de: {path: "/assets/trads/de.json", trads: {…}}
en: {path: "/assets/trads/en.json", trads: {…}}
es: {path: "/assets/trads/es.json", trads: {…}}
fr: {path: "/assets/trads/fr.json", trads: {…}}
it: {path: "/assets/trads/it.json", trads: {…}}
nl: {path: "/assets/trads/nl.json", trads: {…}}
ru: {path: "/assets/trads/ru.json", trads: {…}}
__proto__: Object
这是我登录时的类型:
Object
如果我尝试:
console.log(obj.en);
console.log(obj['en']);
console.log(obj.length);
我得到:
undefined
如果我做:
Object.keys(obj).forEach(e => console.log(e));
for (let i in obj) { console.log(obj[i] }
for (let i in obj) { console.log(i) }
我什么都得不到。
我如何从 createTradsObjFrom() 制作对象(在客户端运行,获取包含某些内容翻译的 JSON 文件):
const getJson = path => {
return new Promise((resolve, reject) => {
$.getJSON(path, json => {
if (!json) return reject(new Error('Error while trying to get json for assets trads.'));
return resolve(json);
});
});
};
const createTradsObjFrom = (languages, tradsPaths) => {
return new Promise((resolve, reject) => {
try {
const obj = {};
languages.forEach(async (lang, index) => {
const path = tradsPaths[index];
obj[lang] = {
path,
trads: await getJson(path)
};
});
console.log('obj : ', obj);
return resolve(obj);
}
catch (err) {
return reject(new Error(err));
}
});
};
const getTrads = currentLanguage => {
return new Promise((resolve, reject) => {
const tradsDir = "/assets/trads/";
const languages = [
"de",
"en",
"es",
"fr",
"it",
"nl",
"ru"
];
const tradsPaths = languages.map(e => tradsDir + e + '.json');
createTradsObjFrom(languages, tradsPaths)
.then(trads => resolve(trads))
.catch(err => reject(err));
});
};
感谢您的帮助,我已经在这方面花费了太多时间。:)
解决方案
首先,您正在使用一种反模式为已经返回 promise/thenable 的调用创建 promise。例如$.getJSON
返回一个可await
直接使用的对象
const getJson = path => {
return $.getJSON(path);
};
//or just change
trads: await getJson(path)
//to use $.getJSON directly
trads: await $.getJSON(path)
其次forEach()
,不使用承诺,因此使其回调async
无关紧要,因为它不会等待承诺解决。您需要使createTradsObjFrom
自身异步并使用正常循环
const createTradsObjFrom = async (languages, tradsPaths) => {
try {
const obj = {};
//set index,lang by destructuring
for(let [index,lang] of languages.entries()){
const path = tradsPaths[index];
obj[lang] = {
path,
//just call $.getJSON directly unless needing extra work done
trads: await $.getJSON(path)
};
}
console.log('obj : ', obj);
return obj;
}
catch (err) {
//since async functions don't provide a reject method we
//need to throw an error to cause a rejection
throw new Error("some error");
}
};
现在你可以直接返回createTradsObjFrom()
或调用你的 then's
const getTrads = currentLanguage => {
//again don't need to make a new promise here as
//createTradsObjFrom will be returning one itself
const tradsDir = "/assets/trads/";
const languages = ["de","en","es","fr","it","nl","ru"];
const tradsPaths = languages.map(e => tradsDir + e + '.json');
return createTradsObjFrom(languages, tradsPaths);
};
getTrads().then(yourObj=>{
console.log(yourObj);
//you can now use your filled object
}).catch(err=>{
console.log("Some error happened: ",err);
});
至于为什么您在控制台日志中看到该对象已填充,请参阅有关控制台如何在控制台中第一次扩展对象时评估对象的问答:Chrome 的 JavaScript 控制台是否懒于评估数组?
推荐阅读
- javascript - 如何在循环中处理 Promise
- angular - 使用剑道网格角度获取孔选定对象
- mysql - SQLAlchemy 1.4 ORM is_distinct_from() 导致意外错误?
- macos - MacOS M1上的Docker kafka问题停留在配置上
- safari - Safari - AppleScript 不会移动到 bookdown 在线图书的下一部分
- python - 即使有时对象为空,也可以在列表中保留位置
- php - 如何在使用 v-for 通过 vuejs 打印数据时提供带有刀片的路由?
- haskell - 2 个使用 do 表示法的类似 Haskell 函数返回相同的结果,但其中一个被调用多次
- docker - 如何通过 OpenVPN 客户端向所有 VPN 客户端公开 docker 网络
- mysql - 无法在 Windows 10 上将 lower_case_table_names 设置为 0