Как написать асинхронные функции для Node.js - PullRequest
110 голосов
/ 01 августа 2011

Я пытался выяснить, как именно следует писать асинхронные функции.После долгих поисков документации мне все еще непонятно.

Как мне написать асинхронные функции для Node?Как правильно реализовать обработку событий ошибок?

Еще один способ задать мой вопрос заключается в следующем: Как мне интерпретировать следующую функцию?

var async_function = function(val, callback){
    process.nextTick(function(){
        callback(val);
    });
};

Также я нашел этот вопрос по SO («Как создать неблокирующую асинхронную функцию в node.js?») Интересен.Я не чувствую, что на него уже ответили.

Ответы [ 6 ]

84 голосов
/ 01 августа 2011

Вы, кажется, путаете асинхронный ввод-вывод с асинхронными функциями.node.js использует асинхронный неблокирующий ввод-вывод, потому что лучше не блокирующий ввод-вывод.Лучший способ понять это - посмотреть видео от Райана Дала.

Как мне написать асинхронные функции для узла?

Простописать нормальные функции, единственное отличие состоит в том, что они не выполняются сразу, а передаются как обратные вызовы.

Как правильно реализовать обработку событий ошибок

Обычно API выдают обратный вызов с ошибкой в ​​качестве первого аргумента.Например,

database.query('something', function(err, result) {
  if (err) handle(err);
  doSomething(result);
});

- это обычный шаблон.

Другой распространенный шаблон - on('error').Например,

process.on('uncaughtException', function (err) {
  console.log('Caught exception: ' + err);
});

Редактировать:

var async_function = function(val, callback){
    process.nextTick(function(){
        callback(val);
    });
};

Приведенная выше функция при вызове как

async_function(42, function(val) {
  console.log(val)
});
console.log(43);

Распечатает 42 наконсоль асинхронно.В частности, process.nextTick срабатывает после того, как текущий стек вызовов Eventloop пуст.Этот стек вызовов становится пустым после выполнения async_function и console.log(43).Таким образом, мы печатаем 43, а затем 42.

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

9 голосов
/ 17 июля 2014

Недостаточно просто проходить обратные вызовы. Вы должны использовать settimer, например, чтобы сделать функцию асинхронной.

Примеры: Не асинхронные функции:

function a() {
  var a = 0;    
  for(i=0; i<10000000; i++) {
    a++;
  };
  b();
};

function b() {
  var a = 0;    
  for(i=0; i<10000000; i++) {
    a++;
  };    
  c();
};

function c() {
  for(i=0; i<10000000; i++) {
  };
  console.log("async finished!");
};

a();
console.log("This should be good");

Если вы запустите приведенный выше пример, это должно быть хорошо, придется подождать, пока эти функции не завершат работу.

Псевдо многопоточные (асинхронные) функции:

function a() {
  setTimeout ( function() {
    var a = 0;  
    for(i=0; i<10000000; i++) {
      a++;
    };
    b();
  }, 0);
};

function b() {
  setTimeout ( function() {
    var a = 0;  
    for(i=0; i<10000000; i++) {
      a++;
    };  
    c();
  }, 0);
};

function c() {
  setTimeout ( function() {
    for(i=0; i<10000000; i++) {
    };
    console.log("async finished!");
  }, 0);
};

a();
console.log("This should be good");

Этот будет полностью асинхронным. Это должно быть хорошо написано до того, как асинхронность закончится.

5 голосов
/ 01 августа 2011

Вы должны посмотреть это: Узел Tuts эпизод 19 - Асинхронные итерационные шаблоны

Он должен отвечать на ваши вопросы.

3 голосов
/ 07 марта 2018

Если вы ЗНАЕТЕ, что функция возвращает обещание, я предлагаю использовать новые функции async / await в JavaScript.Синтаксис выглядит синхронно, но работает асинхронно.Когда вы добавляете ключевое слово async в функцию, это позволяет вам await обещаний в этой области:

async function ace() {
  var r = await new Promise((resolve, reject) => {
    resolve(true)
  });

  console.log(r); // true
}

, если функция не возвращает обещание, я рекомендую заключить его в новое обещаниечто вы определяете, затем разрешите данные, которые вы хотите:

function ajax_call(url, method) {
  return new Promise((resolve, reject) => {
    fetch(url, { method })
    .then(resp => resp.json())
    .then(json => { resolve(json); })
  });
}

async function your_function() {
  var json = await ajax_call('www.api-example.com/some_data', 'GET');
  console.log(json); // { status: 200, data: ... }
}

Итог: используйте силу Обещаний.

3 голосов
/ 06 апреля 2013

Попробуйте, это работает как для узла, так и для браузера.

isNode = (typeof exports !== 'undefined') &&
(typeof module !== 'undefined') &&
(typeof module.exports !== 'undefined') &&
(typeof navigator === 'undefined' || typeof navigator.appName === 'undefined') ? true : false,
asyncIt = (isNode ? function (func) {
  process.nextTick(function () {
    func();
  });
} : function (func) {
  setTimeout(func, 5);
});
1 голос
/ 07 декабря 2018

Я выполнил слишком много часов для выполнения такой задачи для node.js.Я в основном фронтмен.

Я нахожу это очень важным, потому что все методы узла асинхронно работают с обратным вызовом, и преобразовать его в Promise лучше с этим справиться.

Я просто хочучтобы показать возможный результат, более тонкий и читабельный.Используя ECMA-6 с асинхронным режимом, вы можете написать это следующим образом.

 async function getNameFiles (dirname) {
  return new Promise((resolve, reject) => {
    fs.readdir(dirname, (err, filenames) => {
      err !== (undefined || null) ? reject(err) : resolve(filenames)
    })
  })
}

* (undefined || null) для сценариев repl (чтение цикла печати события), использование undefined также работает.

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