Вложенные функции Promise.all, дающие неожиданные результаты - PullRequest
0 голосов
/ 10 января 2020

Я пытаюсь перевести записи из файла JSON на другой язык, используя Deepl API. Файл 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, но с переведенными записями. Однако, где-то я ошибся с логикой своего обещания c. Может ли кто-нибудь помочь мне понять это?

Вот что он выполняет:

> 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 Ответ

1 голос
/ 10 января 2020

Вы пропускаете знак равенства после 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.pre, question.body и question.correct в качестве этих значений. Вместо этого они устанавливают для них Обещания, которые вы определили выше:

                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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...