【问题标题】:Create a custom callback in JavaScript在 JavaScript 中创建自定义回调
【发布时间】:2011-01-12 13:09:03
【问题描述】:

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

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 
}

我该如何实现?

【问题讨论】:

  • object.LoadData(success) 调用必须在 function success 定义之后。否则,你会得到一个错误,告诉你函数没有定义。

标签: javascript callback


【解决方案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);

这将调用doSomething,它将调用foo,它会提醒“stuff going here”。

请注意,传递函数reference (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`

【讨论】:

  • 我知道如果我没有像您编写的示例那样的任何参数,它会起作用,但是当我尝试传递带参数的函数时,它会抛出异常并告诉我该函数未定义跨度>
  • @TiTaN:这很奇怪,将参数传递给回调并没有什么特别之处。传递给函数的回调引用与其他函数一样是函数引用,你可以用它做所有正常的事情。
  • @everyone回答:我认为TiTaN的问题是他不知道如何将需要参数的函数传递给不传递任何参数的回调。想想setTimeout()。答案是将回调包装在一个闭包中:doSomething(function(){foo('this','should','work')})
  • 有人将 TiTaN 指向一个讨论上述问题的线程(最好是在 SO 上),我的 search-fu 今天很弱。
  • @Webwoman - 这取决于您的用例。您可以将其作为参数传递,或将其包含在某种设置/选项对象或其他几个选项中。
【解决方案2】:

在尝试执行回调之前确保回调是一个实际的函数是个好习惯:

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

  callback();
}

【讨论】:

  • if(typeof callback == "function") 将得到相同的结果。
  • 是的,但是如果没有回调,为什么还要麻烦 typeof-ing 呢?这就是callback && 的意义所在...
【解决方案3】:

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

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


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

【讨论】:

  • 我喜欢这个 sn-p,我正在寻找这个
【解决方案4】:
function loadData(callback) {

    //execute other requirement

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

loadData(function(){

   //execute callback

});

【讨论】:

  • 请考虑编辑您的帖子,以添加更多关于您的代码的作用以及它为何能解决问题的说明。一个大部分只包含代码的答案(即使它正在工作)通常不会帮助 OP 理解他们的问题。但是在这种情况下,这是一个非常古老的问题,已经发布了备受推崇的答案,当有新的问题需要更多关注时,您可能不值得回答这个问题。
  • 我喜欢这个答案,它展示了人们希望看到的内容。
【解决方案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 !

【讨论】:

    【解决方案6】:

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

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

    回调的意思是,在显示console.log的用户列表之前,总是将“Jake”添加到用户中。

    Source (YouTube)

    【讨论】:

      【解决方案7】:

      如果你想在某事完成后执行一个函数。一个好的解决方案是监听事件。 比如我会用ES6实现一个Dispatcher,一个DispatcherEvent类,那么:

      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:我的代码缺少处理一些错误异常

      【讨论】:

        【解决方案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 的完整示例。

        【讨论】:

          【解决方案9】:
          function LoadData(callback) 
          {
              alert('the data have been loaded');
              callback(loadedData, currentObject);
          }
          

          【讨论】:

            【解决方案10】:

            试试:

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

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

            【讨论】:

              【解决方案11】:
                   function login(email, password, callback) {
                       //verify the user
                       const users = [
                        { email: "abc@gmail.com", password: "123" },
                        { email: "xyz@gmail.com", 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("abc@gmail.com", "123", redirect);
              

              希望这个例子对想了解JS中回调的大家有所帮助

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-06-08
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-06-14
                • 2015-10-01
                相关资源
                最近更新 更多