嵌套的Promise.all函数会产生意外的结果

时间:2020-01-10 14:53:54

标签: javascript asynchronous promise

我正在尝试使用Deepl API将条目从JSON文件转换为另一种语言。 JSON文件如下所示:

[
    {
        "pre": "here is a sample",
        "body": "here is the body",
        "answers": ["answer one", "answer two"],
        "correct": "answer one"
    },
    {
        "pre": "here is a sample",
        "body": "here is the body",
        "answers": ["answer one", "answer two"],
        "correct": "answer one"
    }
]

我正在使用以下功能来做到这一点:

const { exec } = require('child_process');
const fs = require('fs')
const authKey = 'somekey'

module.exports = {

    translateText(text, targetLang){
        return new Promise(function(accept, reject){
            var command=`curl https://api.deepl.com/v2/translate \
    -d auth_key=${authKey} \
    -d "text=${text}"  \
    -d "target_lang=${targetLang}"`;

            exec(command, (err, stdout, stderr) => {
                if (err) {
                    return;
                }
                accept(stdout);
            });

        });
    },
    translateFile(src, targetLang){
        var self=this;
        return new Promise(function(accept, reject){
            fs.readFile(src, function(err, data){
                if(err){
                    return
                }
                const contents=data.toString();
                var arr=JSON.parse(contents);// [{id: 1, pre: '', 'body', 'answers': ['sdf', 'adfwe'], correct: 'sdf'}]

                Promise.all(arr.map(question => {

                    var pre = question.pre=self.translateText(question.pre, targetLang);
                    var body = question.body=self.translateText(question.body, targetLang);
                    var correct = question.correct=self.translateText(question.correct, targetLang);
                    var answers = Promise.all(question.answers.map(answer => {
                        return self.translateText(answer, targetLang);
                    })).then(translated => {
                        answers = translated;
                        Promise.all([pre, body, correct]).then(()=>{
                            question.pre=pre
                            question.body=body
                            question.correct=correct
                            question.answers=answers
                            return question;
                        });
                    });
                    console.log('the answers are: ' + answers);
                    return Promise.all([pre, body, correct, answers]).then(val => {

                        return question
                    });
                })).then(val => {
                    accept(val);
                });
            });
        });

    }
}

我期望将返回一个看起来与原始JSON数组完全相同的数组,但带有转换后的条目。但是,我在某些地方犯了诺言逻辑。谁能帮助我理解这一点?

这是执行它的作用:

> var t=require('./translate.js')
undefined
> t.translateFile('./sample_data.json', 'DE').then(data => {console.log(data)})
Promise {
  <pending>,
  domain:
   Domain {
     domain: null,
     _events:
      { removeListener: [Function: updateExceptionCapture],
        newListener: [Function: updateExceptionCapture],
        error: [Function: debugDomainError] },
     _eventsCount: 3,
     _maxListeners: undefined,
     members: [] } }
> the answers are:
Promise {
  <pending>,
  domain:
   Domain {
     domain: null,
     _events:
      { removeListener: [Function: updateExceptionCapture],
        newListener: [Function: updateExceptionCapture],
        error: [Function: debugDomainError] },
     _eventsCount: 3,
     _maxListeners: undefined,
     members: [] } }
the answers are:
Promise {
  <pending>,
  domain:
   Domain {
     domain: null,
     _events:
      { removeListener: [Function: updateExceptionCapture],
        newListener: [Function: updateExceptionCapture],
        error: [Function: debugDomainError] },
     _eventsCount: 3,
     _maxListeners: undefined,
     members: [] } }
[ { pre:
     Promise {
       '{"translations":[{"detected_source_language":"EN","text":"hier ist ein Beispiel"}]}',
       domain: [Domain] },
    body:
     Promise {
       '{"translations":[{"detected_source_language":"EN","text":"hier ist die Leiche"}]}',
       domain: [Domain] },
    answers:
     [ '{"translations":[{"detected_source_language":"EN","text":"eine Antwort geben"}]}',
       '{"translations":[{"detected_source_language":"EN","text":"zweite Antwort"}]}' ],
    correct:
     Promise {
       '{"translations":[{"detected_source_language":"EN","text":"eine Antwort geben"}]}',
       domain: [Domain] } },
  { pre:
     Promise {
       '{"translations":[{"detected_source_language":"EN","text":"hier ist ein Beispiel"}]}',
       domain: [Domain] },
    body:
     Promise {
       '{"translations":[{"detected_source_language":"EN","text":"hier ist die Leiche"}]}',
       domain: [Domain] },
    answers:
     [ '{"translations":[{"detected_source_language":"EN","text":"eine Antwort geben"}]}',
       '{"translations":[{"detected_source_language":"EN","text":"zweite Antwort"}]}' ],
    correct:
     Promise {
       '{"translations":[{"detected_source_language":"EN","text":"eine Antwort geben"}]}',
       domain: [Domain] } } ]

1 个答案:

答案 0 :(得分:1)

var answers之后,您缺少等号:

                var answers =
                Promise.all(question.answers.map(answer => {
                    return self.translateText(answer, targetLang);
                })).then(translated => {
                    answers = translated;
                    Promise.all([pre, body, correct]).then(()=>{
                        question.pre=pre
                        question.body=body
                        question.correct=correct
                        question.answers=answers
                        return question;
                    });
                });

但是,因为这不是问题所在(并且您已经发布了结果,谢谢!),我最好的猜测是问题出在这里:

                    Promise.all([pre, body, correct]).then(()=>{
                        question.pre=pre
                        question.body=body
                        question.correct=correct
                        question.answers=answers
                        return question;
                    });

您应该捕获.then()中完成的数组,并将question.prequestion.bodyquestion.correct设置为这些值。而是将它们设置为您在上面定义的Promises:

                Promise.all([pre, body, correct]).then((results)=>{
                    question.pre=results[0]
                    question.body=results[1]
                    question.correct=results[2]
                    question.answers=answers
                    return question;
                });

您仍然需要从JSON中解析纯文本。