JavaScriptでカスタムコールバックを作成する


322

現在の関数の実行が終了したら、コールバック関数を実行するだけです。

function LoadData() 
{
    alert('The data has been loaded');
    //Call my callback with parameters. For example,
    //callback(loadedData , currentObject);
}

この関数のコンシューマーは次のようになります。

object.LoadData(success);

function success(loadedData , currentObject) 
{
  //Todo: some action here 
}

これをどのように実装しますか?


3
object.LoadData(success)呼び出しは定義された後で function successある必要があります。そうしないと、関数が定義されていないことを示すエラーが発生します。
J.ブルーニ

回答:


574

実際、コードはほとんどそのまま機能します。コールバックを引数として宣言するだけで、引数名を使用して直接呼び出すことができます。

基礎

function doSomething(callback) {
    // ...

    // Call the callback
    callback('stuff', 'goes', 'here');
}

function foo(a, b, c) {
    // I'm the callback
    alert(a + " " + b + " " + c);
}

doSomething(foo);

それは呼ぶdoSomething呼ぶいる、foo、「ものをここに」警告であろう。

関数を呼び出してその結果()を渡すのではなく、関数参照foo)を渡すことが非常に重要であることに注意してくださいfoo()。あなたの質問では、あなたはそれを適切に行いますが、それは一般的なエラーであるため、指摘するだけの価値があります。

より高度なもの

コールバックを呼び出して、の特定の値を確認したい場合がありますthis。これはJavaScript call関数で簡単に実行できます。

function Thing(name) {
    this.name = name;
}
Thing.prototype.doSomething = function(callback) {
    // Call our callback, but using our own instance as the context
    callback.call(this);
}

function foo() {
    alert(this.name);
}

var t = new Thing('Joe');
t.doSomething(foo);  // Alerts "Joe" via `foo`

引数を渡すこともできます:

function Thing(name) {
    this.name = name;
}
Thing.prototype.doSomething = function(callback, salutation) {
    // Call our callback, but using our own instance as the context
    callback.call(this, salutation);
}

function foo(salutation) {
    alert(salutation + " " + this.name);
}

var t = new Thing('Joe');
t.doSomething(foo, 'Hi');  // Alerts "Hi Joe" via `foo`

コールバックに指定する引数を、個別ではなく配列として渡すと便利な場合があります。あなたapplyはそれを行うために使用できます:

function Thing(name) {
    this.name = name;
}
Thing.prototype.doSomething = function(callback) {
    // Call our callback, but using our own instance as the context
    callback.apply(this, ['Hi', 3, 2, 1]);
}

function foo(salutation, three, two, one) {
    alert(salutation + " " + this.name + " - " + three + " " + two + " " + one);
}

var t = new Thing('Joe');
t.doSomething(foo);  // Alerts "Hi Joe - 3 2 1" via `foo`

私はあなたが書いた例のように任意のパラメータを持っていない場合、それは動作します知っているが、私はそれが例外をスローし、私の機能を伝えるのパラメータを持つ関数を渡すしようとすると、定義されていません
Amgad Fahmi

@TiTaN:奇妙なことですが、コールバックにパラメーターを渡すことに関して特別なことは何もありません。関数に渡すコールバック参照は、他の関数参照と同じように関数参照であり、それを使用して通常のすべてのことを実行できます。
TJクラウダー

4
回答者全員:私はTiTaNの問題は、引数を必要とする関数を、引数を渡さないコールバックに渡す方法を知らないことだと思います。考えてみてくださいsetTimeout()。答えは閉鎖にコールバックをラップすることです:doSomething(function(){foo('this','should','work')})
slebetman

誰かが上記の問題について議論しているスレッド(できればSOのこと)をTiTaNに指摘しましたが、私のsearch-fuは今日弱いです。
slebetman、2010

1
@Webwoman-ユースケースによって異なります。これを引数として渡すか、ある種の設定/オプションオブジェクト、または他のいくつかのオプションに含めることができます。
TJクラウダー

77

実行する前に、コールバックが実際の関数であることを確認することをお勧めします。

if (callback && typeof(callback) === "function") {

  callback();
}

21
if(typeof callback == "function")同じ結果になります。
Reactgular 2013年

22
はい、でもコールバックがない場合は、どうしてタイプ入力するのですか?それがポイントですcallback && ...
theonlygusti 14

61

私の2セント。同じですが異なります...

<script>
    dosomething("blaha", function(){
        alert("Yay just like jQuery callbacks!");
    });


    function dosomething(damsg, callback){
        alert(damsg);
        if(typeof callback == "function") 
        callback();
    }
</script>

7
私はこのスニペットが大好きで、これを探していました
vimal1083 14年

10
function loadData(callback) {

    //execute other requirement

    if(callback && typeof callback == "function"){
        callback();
   }
}

loadData(function(){

   //execute callback

});

6
投稿を編集して、コードの機能と問題を解決する理由を詳しく説明してください。通常、コードが含まれているだけの回答(たとえそれが機能していても)は、通常、OPが問題を理解するのに役立ちません。ただし、この場合、これは非常に古くからある質問であり、すでに高く評価された回答が投稿されています。より注意を払うことができる新しい質問がある場合、これに答える価値はないかもしれません。
SuperBiasedMan

1
私はこの答えが好きです。人々が見たいものをstr8でデモンストレーションします。
Aft3rL1f3

5
   function callback(e){
      return e;
   }
    var MyClass = {
       method: function(args, callback){
          console.log(args);
          if(typeof callback == "function")
          callback();
       }    
    }

==============================================

MyClass.method("hello",function(){
    console.log("world !");
});

==============================================

結果は次のとおりです。

hello world !

4

何かが行われたときに関数を実行したい場合。良い解決策の1つは、イベントをリッスンすることです。たとえば、ES6を使用しDispatcherDispatcherEventクラスを実装すると、次のようになります。

let Notification = new Dispatcher()
Notification.on('Load data success', loadSuccessCallback)

const loadSuccessCallback = (data) =>{
   ...
}
//trigger a event whenever you got data by
Notification.dispatch('Load data success')

発車係:

class Dispatcher{
  constructor(){
    this.events = {}
  }

  dispatch(eventName, data){
    const event = this.events[eventName]
    if(event){
      event.fire(data)
    }
  }

  //start listen event
  on(eventName, callback){
    let event = this.events[eventName]
    if(!event){
      event = new DispatcherEvent(eventName)
      this.events[eventName] = event
    }
    event.registerCallback(callback)
  }

  //stop listen event
  off(eventName, callback){
    const event = this.events[eventName]
    if(event){
      delete this.events[eventName]
    }
  }
}

DispatcherEvent:

class DispatcherEvent{
  constructor(eventName){
    this.eventName = eventName
    this.callbacks = []
  }

  registerCallback(callback){
    this.callbacks.push(callback)
  }

  fire(data){
    this.callbacks.forEach((callback=>{
      callback(data)
    }))
  }
}

幸せなコーディング!

p / s:いくつかのエラー例外を処理するコードがありません



1

コールバック関数を呼び出すとき、以下のように使用できます。

consumingFunction(callbackFunctionName)

例:

// Callback function only know the action,
// but don't know what's the data.
function callbackFunction(unknown) {
  console.log(unknown);
}

// This is a consuming function.
function getInfo(thenCallback) {
  // When we define the function we only know the data but not
  // the action. The action will be deferred until excecuting.
  var info = 'I know now';
  if (typeof thenCallback === 'function') {
    thenCallback(info);    
  }
}

// Start.
getInfo(callbackFunction); // I know now

これは、完全な例を持つCodependです。


1

いくつかの答えは正しいですが、理解するのが少し難しいかもしれません。これが素人の言葉での例です:

var users = ["Sam", "Ellie", "Bernie"];

function addUser(username, callback)
{
    setTimeout(function()
    {
        users.push(username);
        callback();
    }, 200);
}

function getUsers()
{
    setTimeout(function()
    {
        console.log(users);
    }, 100);
}

addUser("Jake", getUsers);

コールバックとは、「Jake」が常にユーザーに追加されてから、でユーザーのリストを表示することを意味しconsole.logます。

ソース(YouTube)


0

試してください:

function LoadData (callback)
{
    // ... Process whatever data
    callback (loadedData, currentObject);
}

関数はJavaScriptの最初のクラスです。あなたはそれらを単に渡すことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.