如何在循环并进行异步承诺调用后获取重新格式化的 json 对象
Posted
技术标签:
【中文标题】如何在循环并进行异步承诺调用后获取重新格式化的 json 对象【英文标题】:How to get a re-formatted json object after looping over it and making asynchronous promise calls 【发布时间】:2017-12-25 13:00:22 【问题描述】:不确定问题是对还是错。让我简单描述一下问题以便更好地理解。考虑一个多级 json 对象,其键具有随机英文文本字符串作为其值。任务是遍历对象并访问每个节点以创建另一个等效对象,其中包含与以前相同的父对象具有相同键(和级别)的那些英语字符串的翻译文本。使用递归翻译是有效的,但是在一个承诺中它永远不会返回最终的翻译对象。不过没有错误。
对象:
var obj =
"MENU":
"NODE": "Wait for her",
"RESPONSE":
"ATTR": "We'll meet again",
"SEMANTICS": "The Dark Knighthood"
,
"NODES":
"STANDARDLIBRARY":
"SERVER": "Never say never again",
"CATEGORIES":
"INFOPROTECTION":"Infoprotection",
"DATAMOTION":"Data In Motion",
"LOGGING":"Loggin is key to debugging",
"VERACITY": "Help me understand the best I can",
"VARIETY": "Silver surfer"
;
代码:
const iterateAttributesAndParseJSON = (o) =>
return new Promise(
function (resolve, reject)
for(var a in o)
if (typeof o[a] == 'object')
iterateAttributesAndParseJSON(o[a])
else
if( o[a] != '' )
translate(o[a], from: 'en', to: 'nl').then( res =>
//return jsonObj[a]=res.text;
jsonObj[a]=res.text;
//console.log(jsonObj);
resolve(jsonObj);
).catch(err =>
console.error(err)
reject(err);
);
);
iterateAttributesAndParseJSON(obj).then(asd => console.log(`Resolved:`, asd) , err => console.log(err))
注意:翻译又是可以的。我使用了这个 npm 模块。 google-translate-api
【问题讨论】:
也许我遗漏了一些东西,但是在调用翻译之后你会立即调用返回。这是否意味着接下来的三行将不会被执行(包括 resolve())? 请立即查看。在原始代码中,return 被注释掉了。我在贴这里的时候打开错了。 此时我唯一能想到的是,在递归调用之后你没有解决它。对我来说,我没有得到任何输出“已解决”,只有函数内的控制台日志。但这里已经很晚了,我得把它收拾好。祝你好运,我明天可能会看看,因为这个问题很有趣。 嗯,不确定但resolve(jsonObj);
不会做这项工作吗?
我找到了另一个 npm 模块,它可能使我能够做到这一点。 :translate-json-object 但是,这个问题对我来说似乎很有趣。我需要查看这个 npm 模块代码库,看看它们是如何管理事物的。我只是无法理解异步性。
【参考方案1】:
我认为您可以使用 promise all 来完成工作,而不是优化代码但可以工作。
const translate = require('google-translate-api');
//var jsonObj = ;
var obj =
"MENU":
"NODE": "Wait for her",
"RESPONSE":
"ATTR": "We'll meet again",
"SEMANTICS": "The Dark Knighthood"
,
"NODES":
"STANDARDLIBRARY":
"SERVER": "Never say never again",
"CATEGORIES":
"INFOPROTECTION": "Infoprotection",
"DATAMOTION": "Data In Motion",
"LOGGING": "Loggin is key to debugging",
"VERACITY": "Help me understand the best I can",
"VARIETY": "Silver surfer"
;
var promises = [];
const iterateAttributesAndParseJSON = (o) =>
for (var a in o)
if (typeof o[a] == 'object')
iterateAttributesAndParseJSON(o[a]);
else
if (o[a] != '')
var promise = translate(o[a], from: 'en', to: 'nl' ).then(res =>
var jsonObj = ;
jsonObj[a] = res.text;
return jsonObj;
).catch(err =>
console.error(err)
// reject(err);
);
promises.push(promise);
iterateAttributesAndParseJSON(obj);
console.log(promises.length);
Promise.all(promises).then(asd => console.log(`Resolved:`, asd) , err => console.log(err))
将打印键和翻译的数组,希望这会有所帮助
【讨论】:
【参考方案2】:我考虑了一下。我会为此使用非常不同的设计。它更简单,不需要 Promises,只需要一次网络调用
var obj =
"MENU":
"NODE": "Wait for her",
"RESPONSE":
"ATTR": "We'll meet again",
"SEMANTICS": "The Dark Knighthood"
,
"NODES":
"STANDARDLIBRARY":
"SERVER": "Never say never again",
"CATEGORIES":
"VERACITY": "Help me understand the best I can",
"VARIETY": "Silver surfer"
;
var vals = [];
shadow = JSON.parse(JSON.stringify( obj ));
function traverse(obj, shadow, vals, cb)
if (typeof obj == 'object')
for (var i in obj)
if (typeof obj[i] == 'object')
traverse(obj[i], shadow[i], vals, cb);
else
cb(i, obj, shadow, vals);
else
return false;
//setup shadow and array of values
traverse(obj, shadow, vals, function(key, o, s, v)
v.push(o[key]);
s[key] = v.length - 1;
);
function callService( cb )
console.log('... calling translation service... please wait..');
setTimeout( function()
//call translation Service HERE use array vals if service accepts arrays
// or vals.join(DELIM); where DELIM is something you know the service won't touch
cb(vals.map( function(v) return v + '-translated'));
, 1000);
callService( function(translatedArr)
traverse(obj, shadow, vals, function(key, o, s, v)
o[key] = translatedArr[s[key]];
);
console.log( obj );
);
如果你喜欢请告诉我。
【讨论】:
以上是关于如何在循环并进行异步承诺调用后获取重新格式化的 json 对象的主要内容,如果未能解决你的问题,请参考以下文章