Tworzenie niestandardowego połączenia zwrotnego w JavaScript

Wszystko, co muszę zrobić, to wykonać funkcję zwrotną, gdy kończy się moja bieżąca realizacja funkcji.

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

Konsument dla tej funkcji powinien wyglądać następująco:

object.LoadData(success);

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

Jak to zaimplementować?

Author: Rubén, 2010-02-03

10 answers

Właściwie, Twój kod będzie działać tak, jak jest, po prostu zadeklaruj swoje wywołanie zwrotne jako argument i możesz wywołać go bezpośrednio za pomocą nazwy argumentu.

Podstawy

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);

Które wywołają doSomething, które wywołują foo, które ostrzegają "rzeczy idą tutaj".

Zauważ, że bardzo ważne jest, aby przekazać odwołanie do funkcji (foo), zamiast wywoływać funkcję i przekazywać jej wynik (foo()). W twoim pytaniu robisz to poprawnie, ale warto wskazując, ponieważ jest to częsty błąd.

Bardziej zaawansowane rzeczy

Czasami chcesz wywołać callback, aby zobaczył określoną wartość dla this. Możesz to łatwo zrobić za pomocą funkcji 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`

Można również podać argumenty:

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`

Czasami warto przekazać argumenty, które chcemy przekazać jako tablicę, a nie pojedynczo. Możesz użyć apply, aby to zrobić:

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`
 578
Author: T.J. Crowder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-16 05:27:49

Dobrą praktyką jest upewnienie się, że wywołanie zwrotne jest rzeczywistą funkcją przed próbą jej wykonania:

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

  callback();
}
 78
Author: Donald A Nummer Jr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-10 23:21:52

Mój 2 cent. To samo, ale inne...

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


    function dosomething(damsg, callback){
        alert(damsg);
        if(typeof callback == "function") 
        callback();
    }
</script>
 65
Author: K. Kilian Lindberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-09 15:23:31
function loadData(callback) {

    //execute other requirement

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

loadData(function(){

   //execute callback

});
 12
Author: arun bahal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-07 09:44:44
   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 !");
});

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

Wynik to:

hello world !
 5
Author: Eyad Farra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-05 21:05:04

Jeśli chcesz wykonać funkcję, gdy coś jest zrobione. Jednym z dobrych rozwiązań jest słuchanie wydarzeń. Na przykład zaimplementuję Dispatcher, A DispatcherEvent klasę z ES6, następnie:

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')

Dispatcher:

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)
    }))
  }
}
Szczęśliwego kodowania!

P/ s: brakuje mojego kodu obsługuj niektóre wyjątki błędów

 4
Author: hien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-16 07:21:22

Niektóre odpowiedzi, choć poprawne, mogą być nieco trudne do zrozumienia. Oto przykład w pojęciach laika:

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);

Wywołanie zwrotne oznacza, że "Jake" jest zawsze dodawany do użytkowników przed wyświetlaniem listy użytkowników z console.log.

Źródło (YouTube)

 2
Author: Dan Bray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-06 00:04:44
function LoadData(callback) 
{
    alert('the data have been loaded');
    callback(loadedData, currentObject);
}
 1
Author: Thomas Bonini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-21 14:28:49

Podczas wywoływania funkcji callback, możemy użyć jej jak poniżej:

consumingFunction(callbackFunctionName)

Przykład:

// 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

To jest Codepend z pełnym przykładem.

 1
Author: Eric Tan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-07 13:57:38

Try:

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

Funkcje są pierwszą klasą w JavaScript ; możesz je po prostu przekazać.

 0
Author: K Prime,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-19 09:28:13