1011 TIL(コールバック関数)

29216 ワード


よくわからなくてもゆっくりできます!ああ、来い.
参考:Dream Coding by ElizabascriptチュートリアルYouTube

コールバック関数


JavaScriptは同期の子供です.すなわち,コードがエスケープされてから,コードは我々が作成した順序で次々と同期して実行される.はい、ここのハウスティンは何ですか.var変数や関数宣言は自動的に一番上に上昇します.
これは、コードが起動されると、コードが表示される順序で自動的に実行されることを意味します.
例を見るとconsoleですlog (1) (2) (3); 作成後、出力が1.2.3であることがわかります.
したがって,動機はコードが所定の順序で実行される.
非同期とは、コードがいつ実行されるか予測できないことです.良い例としては、setTimeout()というWeb APIがある.これはブラウザが提供するAPIで、指定した時間後に渡された関数(コールバック関数)を呼び出します.
コールバック関数は「私たちがあなたに渡した関数です.後で私を呼んでください」です.という形式のものになります.setTimeout()関数は、いつタイムアウトするかを指定するHandler Time Handlerというコールバック関数を提供します.
console.log('1');
setTimeout(function(){
  console.log('2');
}, 1000);
console.log('3');
私たちが指定した時間は1000で1秒です.1秒後、私たちが渡した関数が実行されます.cosole.私はあなたにlog(「2」)を実行させます.でもどうしたの?上から、コードが下りてきて、1,2,3の順番ではなく、1,3-(2秒後)-2のように行います.
まずはコンソールlog(「1」)に遭遇したら、まず1を出力してください.
そしてsettimeoutかな?それはブラウザAPIなので、「ブラウザよ、私はあなたに要求があります.1秒後に私があなたに転送したコールバックを実行してください」と要求しました.このようなブラウザAPIは、まずブラウザに要求を送信しなければならない.
次にコンソールで、応答を待たない.ログ("3").
だから3を出力しますブラウザでは、時間が1秒過ぎてから再び「1秒過ぎて、このコールバック関数を出力します.」その時になって初めて知った.log(「2」)が出力されます.
これが非同期実行方法です.

コールバック最終クリア


ここでは、私たちが渡した関数はすぐに実行されるのではなく、settimeoutという関数にパラメータパラメータを渡し、私たちが指定した、私たちが作成した関数です.だから今すぐ実行しないで、あなたは後で1秒後に私の関数を実行します.
私の関数をもう一度呼んでください.Calback関数と呼ばれます.
通常、これらは矢印関数として宣言するのではなく、簡単な伝達関数です.
console.log('1');
setTimeout(() => console.log('2'), 1000);
console.log('3');
では、ここまで、動機と非同期について理解しました.
では、コールバックは常に非同期で使用されますか?いいえ.
コールバックも2つのケースに分かれています.
インスタント同期コールバックと
非同期コールバックに分かれており、いつ実行されるか分かりません.
パラメータとしてコールバックを受け入れ、処理する関数を作成します.
function printImmediately(print) {
  print();
}
printImmediately()
printImmedialyが何なのか分かりませんが、printというコールバックを受信し、すぐにコールバックを実行する関数を作成してみてください.この関数を使用するとprintImmedialyが呼び出されます.printというコールバック関数を直接受信しますよね?またjavascriptはタイプではないため、コールバック関数のタイプを予測できませんが、パラメータを渡さない簡単なフォーマットを渡してコンソールに出力しようとします.
console.log('1');
setTimeout(() => console.log('2'), 1000);
console.log('3');

// 동기적 콜백
function printImmediately(print) {
  print();
}
printImmediately(()=> console.log('hello'));
helloはすぐに出力され、私たちが前に作成した2は1秒後に出力されます.JavaScriptエンジンはどうやって作りますか?
関数の宣言は反発していると言ったからです
コードを簡単に移動しましょう.
function printImmediately(print) {
  print();
}

console.log('1');
setTimeout(() => console.log('2'), 1000);
console.log('3');

// 동기적 콜백
printImmediately(()=> console.log('hello'));
関数の宣言を一番上に置きます.次に、次のコードが順次宣言され、1が出力され、ブラウザが要求され、3が呼び出され、下位関数が直接呼び出され、これらの関数が直接印刷されます.
1、3、helloの後に2を出力します.
非同期コールバックを実現する方法.
function printImmediately(print) {
  print();
}

console.log('1');
setTimeout(() => console.log('2'), 1000);
console.log('3');

// 동기적 콜백
printImmediately(()=> console.log('hello'));

//비동기 콜백
function printWithDelay(print, timeout) {
  setTimeout(print, timeout);
}
printWithDelay(()=> console.log('async callback'), 2000);
printWithDelayは2つのパラメータprintとtimeoutを受信するしたがって、ブラウザAPIを使用してprintというコールバック関数を呼び出し、最終的にsettimeoutを囲む関数であるtimeoutというパラメータを渡します.settimeoutに渡されたprintとtimeoutを要求します.
呼び出したい場合はprintWithDelay()=>consoleです.log('async callback'), 2000); こうやってプリントアウトしたら.
1(即時出力)
3(即時出力)
hello(print関数を直ちに出力)
2(1秒後)
async callback(2秒後)
このように伝わる
JavaScriptエンジンはどのように理解されていますか?
function printImmediately(print) {
  print();
}

function printWithDelay(print, timeout) {
  setTimeout(print, timeout);
}
console.log('1'); // 동기
setTimeout(() => console.log('2'), 1000); // 비동기
console.log('3'); // 동기
printImmediately(()=> console.log('hello')); // 동기
printWithDelay(()=> console.log('async callback'), 2000); // 비동기

地獄体験

const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(
  id,
  password,
  user => {
    userStorage.getRoles(
      user,
      userWithRole => {
        alert(
          `hello ${userWithRole.name}, you have a ${userWithRole.role} role`
        );
      },
      error => {
        console.log(error);
      }
    );
  },
  error => {
    console.log(error);
  }
);
地獄の問題.毒性が低下する.
これを修正しましょう.
class UserStorage {
  loginUser(id, password) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (
          (id === 'kimel' && password === 'kimhr08') ||
          (id === 'khr3207' && password === 'kimhr461011')
        ) {
          resolve(id);
        } else {
          reject(new Error('not found'));
        }
      }, 2000);
    });
  }

  getRoles(user) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (user === 'kimel') {
          resolve({name: 'kimel', role: 'admin'});
        } else {
          reject(new Error('no access'));
        }
      }, 1000);
    });
  }
}


const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage
  .loginUser(id, password)
  .then(userStorage.getRoles)
  .then(user => alert(`Hello ${user.name}, you have a ${user.role} role`))
  .catch(console.log);
※私が用意した内容にまとめる
時間のかかるタスク(ネットワーク、ファイルの読み取り)については、Promiseを使用して非同期処理を行うことが望ましい.
Promiseを作成すると、渡されたexecutor関数が自動的に実行されます.
Promiseでは、discreteとdiscreteというコールバック関数を受信するexecutorというコールバック関数を渡す必要があります.
Consumers: then, catch, finally
.then()-成功時
.catch()-失敗した場合
.finally()-成功しても失敗しても呼び出されます.
.then()は値を直接渡すこともPromiseルールを渡すこともできます.
コールバック関数を渡すときに受信値を直接使用して関数を呼び出す場合は省略できます.
ex)
.then(食=>console.log(食))
.then(console.log)と書くことができます.