web-dev-qa-db-ja.com

NodeJSでの非同期/待機について理解する

それについての私の理解は、。NETの_async/await_の経験によって影響を受ける可能性があると思うので、いくつかのコード例が必要です。

Express Controllerを5秒間待機させてから、応答を返そうとしています。

_const getUsers = async (ms) => {
  var wait = ms => new Promise(resolve => setTimeout(resolve, ms));

  await wait(ms);
};


export const index = (req, res) => {
  async () => {
    await getUsers(5000);

    res.json([
      {
        id: 1,
        name: 'John Doe',
      },
      { id: 2,
        name: 'Jane Doe',
      },
    ]);
  };
};
_

このコードは機能せず、ブラウザはロードとロードを続け、何も表示しません。

this SO answer に基づいて構築したgetUser関数と、それがどのように機能するかについての私の(誤った)理解に基づいたコントローラーメソッドなので、いくつかの説明と修正が必要です:

1。いつawaitを使用する必要がありますか

私の理解では、await関数呼び出しの前にasyncを使用する必要があります。これは正しいです?また、promiseを返す非同期でない関数の前にawaitを呼び出すことができるのはなぜですか?

2。いつasyncを使用する必要がありますか

私の理解では、関数をasyncとしてマークして、awaitキーワードで呼び出すことができるようにします。これは正しいです?また、[なぜ] await getUsers(5000)呼び出しを匿名の非同期関数でラップする必要があるのですか?

10

いくつかの疑問を解消するには-

  1. awaitは、promiseを返す任意の関数で使用できます。待っている関数は必ずしもasyncである必要はありません。
  2. 関数内でasyncキーワードを使用する場合は、await関数を使用する必要があります。関数内でawaitキーワードを使用しない場合は、その関数をasyncにする必要はありません。
  3. async関数は、デフォルトでpromiseを返します。これが、awaitasync関数を実行できる理由です。

From [〜#〜] mdn [〜#〜] -

非同期関数が呼び出されると、Promiseが返されます。

あなたのコードに関する限り、それはこのように書くことができます-

const getUsers = (ms) => { // No need to make this async
    return new Promise(resolve => setTimeout(resolve, ms));
};

// this function is async as we need to use await inside it
export const index = async (req, res) => {
    await getUsers(5000);

    res.json([
      {
        id: 1,
        name: 'John Doe',
      },
      { id: 2,
        name: 'Jane Doe',
      },
    ]);
};
13
Jyotman Singh

await関数で任意のpromiseをasyncできます。 awaitの後のコードは、あなたが待っている約束が終わった後に実行されます。

これは、従来のJavaScriptコールバックの優れた代替手段です。

私はそれについてブログを書きました-> https://github.com/Gameye/js-async これがあなたのお役に立てば幸いです!

4
Elmer

async awaitは、約束の単なる構文糖衣です。

関数の完了時にコードを実行する場合は、promiseを使用するのと同じように使用します。

async function asyncOperation(callback) {
    const response = await asyncStep1();
    return await asyncStep2(response);
}

promiseland構文を使用した場合は正確です。

function asyncOperation() {
  return asyncStep1(...)
    .then(asyncStep2(...));
}

新しいasync/await構文を使用すると、引き続きPromisesを使用できますが、チェーンされたthen()メソッドにコールバックを提供する必要がなくなります。

代わりに、コールバックは、同期ブロッキング関数であるかのように、非同期関数から直接返されます。

let value = await myPromisifiedFunction(); 

関数でawaitを使用する場合は、関数にasyncキーワード(c#のように)を付ける必要があります。

GetUsersを無名関数として作成する必要はありません。

1
Tal Avissar

Javascriptの非同期関数

asyncキーワードは、通常のJS関数宣言を非同期関数宣言に変換します。

function syncFunc {// dostuff}
async function asyncFunc {// dostuff} // the async keyword is placed before the function keyword

非同期関数Promiseを返します:

  • Async関数が値を返すと、Promiseは戻り値で解決されます。
  • Async関数が例外または何らかの値をスローすると、Promiseはスローされた値で拒否されます。

非同期関数内では、awaitキーワードを使用できます。 awaitをpromiseの前に配置すると、promiseが解決される(拒否されるか実行される)まで非同期関数が一時停止します

  • 。 promiseが満たされたときawait式の値は、満たされたpromiseの値です。
  • Promiseが拒否された場合、awaitthrows拒否された値。

例:

function makePromise(x) { 
    return new Promise(resolve => {
      setTimeout(() => {
        resolve(x);
      }, 1000);
    });
  }
  
  async function asyncFunc() {
    var x = await makePromise(1); // the function is paused here until the promise is fulfilled
    console.log(x); // logs 1
    return x;
  }
  
  const returnedProm = asyncFunc(); // the async func returns a promise


  returnedProm.then((x) => console.log(x));
  // This promise is fulfilled with the return value from the async func, so this logs 1

非同期関数を使用する場合:

非同期関数は、相互に依存する複数の非同期アクション(promiseとして実装)がある場合に便利なツールです。たとえば、2番目の約束が最初の約束が提供するデータを必要とする場合です。これで、awaitキーワードを使用して、最初にpromise 1のデータを受信し、次にこのデータを引数としてpromise2に渡すことができます。

言い換えると、非同期関数はawaitキーワードを介して、非同期プログラミングを同期プログラミングのように動作させることができます。結果として、アプリケーションは理解しやすくなります。

0