如何在循环遍历 JSON 对象并进行异步 Promise 调用后获得重新格式化的 JSON 对象

3
不确定问题是对还是错。让我描述一下问题以便更好地理解。考虑一个多层次的JSON对象,其中键具有随机的英文文本字符串作为它们的值。任务是遍历该对象并访问每个节点,创建另一个等效对象,其中包含那些与之前相同父对象具有相同键(和级别)的英文字符串的翻译文本。使用递归进行翻译是有效的,但是在Promise内部它从未返回最终翻译的对象。尽管没有错误。
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))

注意:Translate现在可以再次使用。我使用了这个npm模块。 google-translate-api

1
也许我漏掉了什么,但在调用翻译后,您立即调用返回。这不意味着下面的三行代码将不会被执行(包括resolve())吗? - Jarek Kulikowski
1
我目前唯一能想到的是,在递归调用之后,你没有解决它。对我来说,我没有得到任何输出“已解决”,只有函数内部的控制台日志。但现在已经很晚了,我得收拾一下今天的工作。祝你好运,因为这个问题很有趣,明天我可能会再看看它。 - Jarek Kulikowski
它不会自己解决,因为那样会太快了,但这就是我的进展。出于好奇,您能否一次发送一个字符串数组以进行翻译,还是必须逐个字符串进行?您正在进行大量调用。 - Jarek Kulikowski
1
我找到了另一个npm模块,可能会让我能够做到这一点。:translate-json-object然而,这个问题对我来说似乎很有趣。我需要检查一下这个npm模块的代码库,看看他们是如何管理事情的。我只是无法理解异步性。 - Smoking Sheriff
@SmokingSheriff 修改了你的代码,使用了 Promise.all,看起来它对你有效。 - gusaindpk
显示剩余2条评论
2个回答

0

我考虑了一下。对于这个问题,我会使用非常不同的设计。它更简单,不需要 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 );
});

请告诉我您是否喜欢它。


0

我认为你可以利用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))

将打印键和翻译的数组,希望这有所帮助


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接