JavaScript のコールバック関数 (同期および非同期) の詳細な分析

青灯夜游
リリース: 2022-08-04 10:05:19
転載
3782 人が閲覧しました

コールバック関数は、すべてのフロントエンド プログラマが知っておくべき概念の 1 つです。コールバックは、配列、タイマー関数、Promise、およびイベント処理で使用できます。この記事では、コールバック関数の概念を説明し、同期と非同期の 2 種類のコールバックを区別するのに役立ちます。

JavaScript のコールバック関数 (同期および非同期) の詳細な分析

1. コールバック関数

まず、人々に挨拶する関数を作成します。

name パラメーターを受け入れる関数 greet(name) を作成するだけです。この関数は挨拶メッセージを返す必要があります:

function greet(name) {
  return `Hello, ${name}!`;
}

greet('Cristina'); // => 'Hello, Cristina!'
ログイン後にコピー

たくさんの人に挨拶したらどうしますか?特別な配列メソッド array.map() を使用して、次のことを実現できます。

const persons = ['Cristina', 'Ana'];

const messages = persons.map(greet);
messages; // => ['Hello, Cristina!', 'Hello, Ana!']
ログイン後にコピー

persons.map(greet) すべての persons## を取得します。 # 配列要素を指定し、各要素を呼び出しパラメーターとして使用して greet() 関数を呼び出します: `greet('Cristina'), greet('Ana')

興味深いことに、

persons.map(greet) メソッドは、パラメータとして greet() 関数を受け入れることができます。このように、greet()コールバック関数 になります。

persons.map(greet) は別の関数をパラメータとして取る関数なので、高階関数と呼ばれます。

コールバック関数高階関数のパラメータとして、高階関数はコールバック関数を呼び出して演算を実行します。
重要なことは、高階関数がコールバックを呼び出し、それに正しいパラメーターを提供する責任があるということです。

前の例では、高階関数

persons.map(greet)greet() 関数を呼び出し、その中のすべての要素を変換します。 array'Cristina' および Ana ' を引数として使用します。

これは、コールバックを識別するための簡単なルールを提供します。関数を定義し、それをパラメータとして別の関数に指定すると、コールバックが作成されます。

コールバックを使用して独自の高階関数を作成できます。

array.map() メソッドの同等バージョンを次に示します。

function map(array, callback) {
  const mappedArray = [];
  for (const item of array) { 
    mappedArray.push(
      callback(item)    );
  }
  return mappedArray;
}

function greet(name) {
  return `Hello, ${name}!`;
}

const persons = ['Cristina', 'Ana'];

const messages = map(persons, greet);messages; // => ['Hello, Cristina!', 'Hello, Ana!']
ログイン後にコピー

map(array, callback) はコールバックを使用するため、高階関数です。関数をパラメータとして指定し、その本体内でコールバック関数を呼び出します: callback(item)

通常の関数 (キーワード

function で定義) またはアロー関数 (太い矢印 => で定義) もコールバックとして使用できることに注意してください。

2. 同期コールバック

コールバックを呼び出すには、

同期コールバックと非同期コールバックという 2 つの方法があります。

同期コールバックは「ブロック」されています。コールバック関数が完了するまで、高階関数は実行を継続しません。

たとえば、

map() 関数と greet() 関数を呼び出します。

function map(array, callback) {
  console.log('map() starts');
  const mappedArray = [];
  for (const item of array) { mappedArray.push(callback(item)) }
  console.log('map() completed');
  return mappedArray;
}

function greet(name) {
  console.log('greet() called');
  return `Hello, ${name}!`;
}

const persons = ['Cristina'];

map(persons, greet);
// logs 'map() starts'
// logs 'greet() called'
// logs 'map() completed'
ログイン後にコピー
その中の

greet() は同期コールバックです。

同期コールバックの手順:

  • 高階関数の実行開始:

    'map() 開始'

  • ##コールバック関数の実行:
  • 'greet() が呼び出された'

  • 。最後に、高階関数は独自の実行プロセスを完了します:
  • ' map() completed'

#同期コールバックの例

多くのネイティブ JavaScript タイプのメソッドは同期コールバックを使用します。

最も一般的に使用されるメソッドは配列です。例:

array.map(callback)

array.forEach(callback)array.find(コールバック ), array.filter(callback), array.reduce(callback, init)<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">// Examples of synchronous callbacks on arrays const persons = ['Ana', 'Elena']; persons.forEach(   function callback(name) {    console.log(name);   } ); // logs 'Ana' // logs 'Elena' const nameStartingA = persons.find(   function callback(name) {    return name[0].toLowerCase() === 'a';   } ); nameStartingA; // =&gt; 'Ana' const countStartingA = persons.reduce(   function callback(count, name) {    const startsA = name[0].toLowerCase() === 'a';     return startsA ? count + 1 : count;   },    0 ); countStartingA; // =&gt; 1</pre><div class="contentsignin">ログイン後にコピー</div></div>String type

string.replace( callback )

メソッドは同期的に実行されるコールバックも受け入れることができます: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">// Examples of synchronous callbacks on strings const person = 'Cristina'; // Replace 'i' with '1' person.replace(/./g,    function(char) {    return char.toLowerCase() === 'i' ? '1' : char;   } ); // =&gt; 'Cr1st1na'</pre><div class="contentsignin">ログイン後にコピー</div></div>

3. 非同期コールバック

非同期コールバックは「ノンブロッキング」です: 高次のコールバックは必要ありません関数 コールバックが完了するまで待って、実行を完了します。高階関数により、コールバックが特定のイベントで後で実行されることが保証されます。

次の例では、

later()

関数の実行が 2 秒遅れます: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">console.log('setTimeout() starts'); setTimeout(function later() {   console.log('later() called'); }, 2000); console.log('setTimeout() completed'); // logs 'setTimeout() starts' // logs 'setTimeout() completed' // logs 'later() called' (after 2 seconds)</pre><div class="contentsignin">ログイン後にコピー</div></div>

later()

は非同期関数です。 callback、setTimeout(later, 2000) は実行を開始して完了しますが、later() は 2 秒後に実行されるためです。 コールバックを非同期で呼び出す手順:

    高階関数の実行開始:
  • 'setTimeout()starts'

  • 高階関数は実行を完了します:
  • 'setTimeout() completed'

  • コールバック関数は 2 秒後に実行されます:
  • 'later( ) が呼び出されます'

非同期コールバックの例

タイマー関数はコールバックを非同期的に呼び出します:

setTimeout(function later() {
  console.log('2 seconds have passed!');
}, 2000);
// After 2 seconds logs '2 seconds have passed!' 

setInterval(function repeat() {
  console.log('Every 2 seconds');
}, 2000);
// Each 2 seconds logs 'Every 2 seconds!'
ログイン後にコピー

DOM イベント リスナーは、イベント処理関数も非同期的に呼び出します (コールバック関数のサブタイプ):

const myButton = document.getElementById('myButton');

myButton.addEventListener('click', function handler() {
  console.log('Button clicked!');
});
// Logs 'Button clicked!' when the button is clicked
ログイン後にコピー

4. 非同期コールバック関数と非同期関数

の前に追加します。関数定義 特別なキーワード

async

は非同期関数を作成します: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">async function fetchUserNames() {   const resp = await fetch('https://api.github.com/users?per_page=5');   const users = await resp.json();   const names = users.map(({ login }) =&gt; login);   console.log(names); }</pre><div class="contentsignin">ログイン後にコピー</div></div> <p><code>fetchUserNames() 是异步的,因为它以 async 为前缀。函数  await fetch('https://api.github.com/users?per_page=5') 从 GitHub 上获取前5个用户 。然后从响应对象中提取 JSON 数据:await resp.json()

异步函数是 promise 之上的语法糖。当遇到表达式 await <promise>  (调用  fetch()  会返回一个promise)时,异步函数会暂停执行,直到 promise 被解决。

异步回调函数和异步函数是不同的两个术语。

异步回调函数由高阶函数以非阻塞方式执行。但是异步函数在等待 promise(await <promise>)解析时会暂停执行。

但是你可以把异步函数用作异步回调!

让我们把异步函数 fetch UserNames() 设为异步回调,只需单击按钮即可调用:

const button = document.getElementById('fetchUsersButton');

button.addEventListener('click', fetchUserNames);
ログイン後にコピー

总结

回调是一个可以作为参数传给另一个函数(高阶函数)执行的函数。

回调函数有两种:同步和异步。

  • 同步回调是阻塞的。

  • 异步回调是非阻塞的。

【相关推荐:javascript学习教程

以上がJavaScript のコールバック関数 (同期および非同期) の詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:segmentfault.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
関連するチュートリアル
人気のおすすめ
最新のコース
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!