Можно ли вернуть значения из асинхронных функций в node.js? - PullRequest
0 голосов
/ 28 июня 2018

Я, вероятно, заново изобретаю колесо, но я хочу создать функцию, которая принимает имя файла и асинхронно возвращает закодированную строку base64.

Я действительно только знаком с обратными вызовами, но также пытаюсь понять обещания. Моя начальная функция обратного вызова выглядит так -

blob2Base64callback.js

module.exports = {
  blob2base64 : function(file) {
    fs.readFile(file, 'utf8', function(err, contents){
      if (err) {
        console.log('file not found');
        return '';
      } else {
        var base64str = Buffer.from(contents).toString('base64');
        console.log(base64str.length);
        return base64str;
      }
    });

  }, //..other functions
}; 

Этот обратный вызов не работает, потому что я на самом деле не возвращаю что-то из функции blob2base4, и если я изменяю это следующим образом:

module.exports = {
  blob2base64 : function(file) {
    return fs.readFile(file, 'utf8', function(err, contents){
      //same implementation as above, cut to improve readability
    });

  }
};  

Возвращает неопределенное значение, потому что не ожидает выполнения. Насколько я знаю, нет никакого способа вернуть что-либо в blob2base64 с помощью обратных вызовов.

Итак, я посмотрел на обещания и попробовал следующее:

blob2Base64promise.js

blob2base64 : function(file) {
  console.log('function called');
  const getFile = new Promise(function(resolve, reject){

    fs.readFile(file, 'utf8', function(err, contents){
      if (err) {
        console.log('file not found');
        reject(err)
      } else {
        //console.log(contents);
        resolve(contents);
      }
    });

  }).then(contents =>{
    var base64str = Buffer.from(contents).toString('base64');
    return base64str;
  }).catch(err => console.log(err));
}

Можно ли в любом случае вернуть обещание функции и извлечь часть разрешения для получения base64str? Правильно ли я думаю, такое поведение возможно только с обещаниями, но без обратных вызовов. Или это невозможно с любым синтаксисом?

Кроме того, я думал, что обратные вызовы и обещания нельзя использовать вместе, но это обещание является просто оболочкой для обратного вызова.

1 Ответ

0 голосов
/ 28 июня 2018

(отвечая в обратном порядке)

Обычно обратные вызовы и обещания не смешиваются, просто потому, что они грязные. Их можно переплетать, если это необходимо. Существуют утилиты для преобразования обратных вызовов в Promises («обещание»), и Promises становятся все более распространенными, особенно с синтаксисом async/await ES6.

Для Обещаний обязательно верните Обещание. В вашем примере return getFile. Что в конечном итоге возвращает цепь Promise, вы должны await. Это могут быть ключевые слова async/await в ES6. Ваш звонок может быть:

асинхронная функция () { let result = await blob2base64 ('myFile.png') }

Какой самый хороший синтаксис для того, чтобы знать, что вы возвращаете Обещание. Вы также можете сделать это так:

function () {
  blob2base64('myFile.png')
  .then( result => {
    // use result here
  })
  // you could catch as well.
}

Для обратных вызовов вам также необходимо передать обратный вызов вашей функции. Вот что делает его асинхронным и где вы даете свои результаты:

blob2base64 : function(file, callback) {
  fs.readFile(file, 'utf8', function(err, contents){
    if (err) {
      console.log('file not found');
      callback(err)
    } else {
      var base64str = Buffer.from(contents).toString('base64');
      console.log(base64str.length);
      callback(null, base64str)
    }
  });

И вы бы назвали это как: blob2base64( 'myFile.png', function (err,result) { })

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