在 JavaScript 中创建自定义回调

Create a custom callback in JavaScript

提问人:Amgad Fahmi 提问时间:2/3/2010 最后编辑:RubénAmgad Fahmi 更新时间:9/27/2021 访问量:376146

问:

我需要做的就是在当前函数执行结束时执行回调函数。

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 
}

如何实现?

JavaScript 回调

评论

3赞 J. Bruni 12/29/2011
object.LoadData(success)call must be after 被定义。否则,您将收到一条错误消息,告诉您未定义该函数。function success

答:

595赞 T.J. Crowder 2/3/2010 #1

实际上,您的代码几乎可以按原样工作,只需将回调声明为参数,然后可以使用参数名称直接调用它。

基础知识

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

这将调用 ,这将调用 ,这将提醒“东西在这里”。doSomethingfoo

请注意,传递函数引用 () 非常重要,而不是调用函数并传递其结果 ()。在你的问题中,你做得很正确,但值得指出,因为这是一个常见的错误。foofoo()

更高级的东西

有时,您希望调用回调,以便它看到 的特定值。您可以使用 JavaScript 函数轻松做到这一点:thiscall

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`

评论

0赞 Amgad Fahmi 2/3/2010
我知道如果我没有任何参数,就像你写的示例一样,它会起作用,但是当我尝试传递一个带有参数的函数时,它会抛出一个异常并告诉我该函数没有定义
0赞 T.J. Crowder 2/3/2010
@TiTaN:这很奇怪,将参数传递到回调中并没有什么特别之处。您传递到函数中的回调引用与其他函数引用一样是函数引用,您可以使用它执行所有正常操作。
4赞 slebetman 2/3/2010
回答@everyone: 我认为 TiTaN 的问题在于他不知道如何将需要参数的函数传递到不传递任何参数的回调中。想。答案是将回调包装在一个闭包中:setTimeout()doSomething(function(){foo('this','should','work')})
0赞 slebetman 2/3/2010
有人将 TiTaN 指向讨论上述问题的线程(最好是在 SO 上),我的搜索 fu 今天很弱。
1赞 T.J. Crowder 2/6/2019
@Webwoman - 这取决于您的用例。您可以将其作为参数传递,或将其包含在某种设置/选项对象或其他几个选项中的任何一个中。
1赞 Andreas Bonini 2/3/2010 #2
function LoadData(callback) 
{
    alert('the data have been loaded');
    callback(loadedData, currentObject);
}
0赞 K Prime 2/3/2010 #3

尝试:

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

函数在 JavaScript 中是一流的;你可以把它们传来传去。

83赞 Donald A Nummer Jr 3/11/2013 #4

在尝试执行回调之前,最好先确保回调是实际函数:

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

  callback();
}

评论

21赞 Reactgular 10/31/2013
if(typeof callback == "function")将产生相同的结果。
24赞 theonlygusti 12/24/2014
是的,但是如果没有回调,为什么还要打字呢?这就是重点......callback &&
67赞 K. Kilian Lindberg 12/9/2013 #5

我的 2 美分。相同但不同......

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


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

评论

9赞 vimal1083 3/14/2014
我喜欢这个片段,我一直在寻找这个
5赞 Eyad Farra 2/16/2014 #6
   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 !
13赞 arun bahal 9/7/2015 #7
function loadData(callback) {

    //execute other requirement

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

loadData(function(){

   //execute callback

});

评论

6赞 SuperBiasedMan 9/7/2015
请考虑编辑您的帖子,以添加更多有关您的代码的作用以及为什么它会解决问题的解释。一个主要只包含代码的答案(即使它有效)通常不会帮助 OP 理解他们的问题。然而,在这种情况下,这是一个非常古老的问题,已经发布了备受推崇的答案,当有新的问题可以引起更多关注时,可能不值得您回答这个问题。
1赞 JΛYDΞV 3/24/2020
我喜欢这个答案,它的 str8 向前演示了人们想看到的东西。
2赞 Eric Tan 4/7/2017 #8

调用回调函数时,我们可以按如下方式使用它:

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

4赞 Dan Bray 2/6/2018 #9

有些答案虽然正确,但可能有点难以理解。这是一个通俗的例子:

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)

4赞 Hien 4/16/2018 #10

如果你想在完成某件事时执行一个函数。一个好的解决方案之一是监听事件。 例如,我将用 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]
    }
  }
}

调度程序事件:

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赞 Muhammad Atif Akram 9/27/2021 #11
     function login(email, password, callback) {
         //verify the user
         const users = [
          { email: "[email protected]", password: "123" },
          { email: "[email protected]", password: "xyz" }
         ];

         const user = users.find(
           (user) => user.email === email && user.password === password
         );
         callback(user);
       `enter code here`}

    function redirect(user) {
       if (user) {
          //user is successfully logged in
          console.log("user is successfully logged in ");
       } else {
         console.log("Incorrect credentials ");
       } 
    }

    
    login("[email protected]", "123", redirect);

我希望这个例子能帮助到所有想了解JS回调的人