Как использовать обратный вызов в JS (узел), чтобы дождаться завершения асинхронной функции, прежде чем продолжить? - PullRequest
0 голосов
/ 01 мая 2019

У меня есть функция translateCommand (команда), которая использует пакет Translate из npm для перевода некоторого текста на другой язык.Проблема заключается в том, что функция translate, предоставляемая этим пакетом, является асинхронной и имеет тенденцию выходить из функции translateCommand до завершения функции translate, что приводит к возврату мусорных данных.и сделал translateCommand (command) асинхронной функцией, чтобы я мог использовать await перед импортированной функцией translate (), которая решила эту проблему, но теперь я просто отложил проблему еще на шаг назад, потому что функция, которая вызывает translateCommand(команда) испытывает точно такую ​​же проблему, и я чувствую, что не добился прогресса, если мне просто придется продолжать повторять эту цепочку вверх.

Дело в том, что я недействительно понимают обещания и то, как асинхронные функции ведут себя в целом по отношению к ним.Я понимаю, что это предпосылка, которая делает Node.js великолепной, но попытка узнать об этом была довольно неэффективной.Попытка решить эту проблему на самом деле не принесла плодов, поскольку все говорят, что используют обратный вызов, не объясняя, что такое обратный вызов.Не помогает, что примеры, как правило, были окружены незнакомым кодом, поэтому я подумал, что получение помощи в контексте моего кода будет касаться двух зайцев одним выстрелом.

Весь этот процесс - моя вводная попытка сделатьглупый Discord Bot, где я реализовал кучу глупых функций.Я много раз сталкивался с асинхронной стеной, но обычно находил синхронную альтернативу, чтобы двигаться вперед.На этот раз я этого не сделал, и я попытался эмулировать обратные вызовы, описанные в других публикациях Stack Overflow, но из-за недостатка понимания не смог правильно их интегрировать (я могу только предположить).

Импортированная функция верхнего уровня, которая теперь имеет проблему асинхронности.

client.on("message", (message) => {

    // ...
    let command = (message.content).substr(1);

    // ...

    // Handles translate command
    else if (command.startsWith("translate"))
        message.channel.send(translateCommand(command));

    // ...
    }
});

Функция, которая была сделана асинхронной, поэтому она может ожидать:

// Form !translate [string]
async function translateCommand(command) {
    let message = "";
    let str = command.substr(10);

    await translate(str, { to: 'ja', engine: 'yandex', key: '<my key>' }).then(function(result) {
        message = result;
        return "";
    });
    return message;
}

Я в курсеэтот вопрос был задан до смерти, но я чувствую, что без контекста, который я понимаю (так как я все еще новичок в JS и Node), я могу продолжить, только ударив головой о стену, пока что-то не сработает, и я не пойму почему.

Ответы [ 3 ]

1 голос
/ 01 мая 2019

Вы также можете изменить функцию верхнего уровня на асинхронную. Измените начало на async (message) => { и используйте message.channel.send(await translateCommand(command)). В качестве альтернативы вы можете использовать обещания, а не делать функцию асинхронной, и вместо этого использовать translateCommand(command).then(msg => message.channel.send(msg)), однако это может привести к путанице в дальнейшем в коде.

0 голосов
/ 01 мая 2019

Используя обещания, вы можете сделать следующее:

translateCommand функция:

var translateCommand = (command) => new Promise((resolve,reject) =>  {
    translate(command.substr(10), { to: 'ja', engine: 'yandex', key: '<my key>' })
        .then(resolve)
        .catch(reject)
    });

затем client.on:

client.on("message", (message) => {

    // ...
    let command = (message.content).substr(1);

    // ...

    // Handles translate command
    else if (command.startsWith("translate"))
        translateCommand(command)
            .then(translationResult => {
               message.channel.send(translationResult)
            })
    // ...
    }
});

Если у вас возникли проблемыс синтаксисом, вот подсказки:
подсказка # 1
подсказка # 2
+ Одно замечание - не бойтесь и не торопитесь, чтобыпрочитайте + внедрите приведенные выше примеры и измените их впоследствии, чтобы вызвать ошибки (вы будете знать, как и когда они работают или не работают - больно, но полезно;))

0 голосов
/ 01 мая 2019

Поскольку translate возвращает обещание, которое вам не нужно давать translateCommand async.Просто верните translate из функции ...

function translateCommand(command) {
  let str = command.substr(10);
  return translate(str, { to: 'ja', engine: 'yandex', key: '<my key>' });
}

... и await обещание выполнить.Вам нужно добавить async к обратному вызову обработчика событий, чтобы await заработал.

client.on("message", async (message) => {

  let command = (message.content).substr(1);

  //...

  else if (command.startsWith("translate"))
    message.channel.send(await translateCommand(command));
    // ...
  }
});
...