web-dev-qa-db-ja.com

Node.jsの非同期関数を作成する方法

私は非同期関数を正確にどのように記述するかを研究しようとしました。多くのドキュメントを徹底的に調べた後、それはまだはっきりしていません。

Nodeの非同期関数を作成するにはどうすればよいですか?エラーイベント処理を正しく実装するにはどうすればよいですか?

私の質問をする別の方法はこれです:どのように私は次の機能を解釈する必要がありますか?

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

また、私はSOに関するこの質問(「node.jsでノンブロッキング非同期関数を作成するにはどうすればよいですか? ") 面白い。まだ答えられた気がしません。

110
Kriem

非同期IOと非同期関数を混同しているようです。 node.jsは、非同期の非ブロック化IOを使用します。これは、非ブロック化IOの方が優れているためです。それを理解する最良の方法は、ライアン・ダールのビデオを見に行くことです。

Nodeの非同期関数を作成する方法

通常の関数を書くだけで、唯一の違いは、それらはすぐには実行されず、コールバックとして渡されることです。

エラーイベント処理を正しく実装する方法

通常、APIは、最初の引数としてerrを含むコールバックを提供します。例えば

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は、現在のイベントループコールスタックが空になった後に発生します。 async_functionおよびconsole.log(43)の実行後、その呼び出しスタックは空になります。したがって、43に続いて42を印刷します。

おそらくイベントループを読む必要があります。

84
Raynos

コールバックを渡すだけでは十分ではありません。たとえば、関数を非同期にするために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");

これは非常に非同期になります。これは、非同期が終了する前に書き込まれます。

9
calmbird

これを見る必要があります: Node Tuts episode 19-Asynchronous Iteration Patterns

質問に答えるはずです。

5
Cris-O

関数がPromiseを返すことを知っているなら、JavaScriptで新しいasync/await機能を使用することをお勧めします。構文は同期的に見えますが、非同期に動作します。関数にasyncキーワードを追加すると、そのスコープ内でawait promiseを使用できます。

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

結論:Promisesの力を活用してください。

3
ryanwaite28

これを試してください。ノードとブラウザの両方で機能します。

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

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を使用しても機能します。

1
Yoarthur