簡體   English   中英

如何為Node.js編寫異步函數

[英]How to write asynchronous functions for Node.js

我試圖研究應該如何編寫完全異步的函數。 經過大量文檔的大量工作后,我仍然不清楚。

如何為Node編寫異步函數? 我該如何正確實現錯誤事件處理?

問我問題的另一種方法是:我應該如何解釋以下功能?

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

另外,我在SO上發現了這個問題 (“如何在node.js中創建非阻塞異步函數?”)。 我覺得它還沒有得到回答。

您似乎將異步IO與異步函數混淆。 node.js使用異步非阻塞IO,因為非阻塞IO更好。 理解它的最好方法是觀看ryan dahl的一些視頻。

如何為Node編寫異步函數?

只寫正常函數,唯一的區別是它們不是立即執行而是作為回調傳遞。

我該如何正確實現錯誤事件處理

通常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 callstack為空后觸發。 async_functionconsole.log(43)運行后,該調用堆棧為空。 所以我們打印43,然后是42。

您應該對事件循環進行一些閱讀。

僅通過回調是不夠的。 例如,您必須使用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");

這個將是異常的異步。 這應該是好的將在異步完成之前寫入。

你應該看一下: Node Tuts第19集 - 異步迭代模式

它應該回答你的問題。

試試這個,它適用於節點和瀏覽器。

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);
});

如果您知道函數返回一個promise,我建議在JavaScript中使用新的async / await功能。 它使語法看起來是同步的,但是異步工作。 async關鍵字添加到函數時,它允許您在該范圍內await promise:

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

  console.log(r); // true
}

如果函數沒有返回一個promise,我建議將它包裝在你定義的新promise中,然后解析你想要的數據:

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: ... }
}

底線:利用Promises的力量。

我為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也可以工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM