2013-12-19 8 views
0

Я хочу выполнить функцию обратного вызова внутри объекта. Я не знаю, что-то не так в том, как я это делаю.Выполнение функции обратного вызова внутри объекта javascript

Я искал решение для Google, также искал в stackoverflow, но не смог найти ничего похожего на то, как я это кодирую.

PHPGateway.js

var PHPGateway = { 

    opt_friendlyURL: true, 
    opt_folder: 'ajax/', 

    callback_function: null, 

    useFriendlyURL: function (bool) { 
     this.opt_friendlyURL = bool; 
    }, 

    setFolder: function (folder) { 
     this.opt_folder = folder; 
    }, 

    send: function (service, method, data, callback) { 
     var url, 
      json_data = {}; 
     if (this.opt_friendlyURL) { 
      url = this.opt_folder + service + '/' + method; 
     } else { 
      url = this.opt_folder + 'gateway.php?c=' + service + '&m=' + method; 
     } 
     if (data != undefined) { 
      json_data = JSON.stringify(data); 
     } 
     this.callback_function = (callback == undefined) ? null : callback; 
     $.ajax({ 
      method: 'POST', 
      url: url, 
      data: {data: json_data}, 
      success: this.ajax_success, 
      error: this.ajax_error 
     }); 
    }, 

    ajax_success: function (returned_object) { 
     if (this.callback_function != null) { 
      this.callback_function(returned_object.error, returned_object.data); 
     } 
    }, 

    ajax_error: function() { 
     this.callback_function.call(false, {}); 
    } 

}; 

Затем внутри HTML-файл, который загружает PHPGateway.js, я следующий код:

<script> 
    function submit_handler(event) { 
     event.preventDefault(); 
     form_submit(); 
    } 
    function form_callback(error, data) { 
     if(error == null) { 
      alert(data.text); 
     } 
    } 
    function form_submit() { 
     var data = { 
      status: $('#inStatus').val(), 
      amount: $('#inAmount').val(), 
      id: $('#inBudgetID'). val() 
     } 
     PHPGateway.send('budget', 'status', data, form_callback); 
    } 
    $('form').one('submit', submit_handler); 
</script> 

Я получаю сообщение об ошибке на this.callback_function(returned_object.error, returned_object.data);, ошибка is Uncaught TypeError: Object # не имеет метода 'callback_function'.

  1. Что я делаю неправильно?
  2. Это лучший способ сделать это?

Thank you!

Основываясь на ответе minitech, я обновил PHPGateway.js следующим образом. Я пропустил те части, которые не были обновлены.

var PHPGateway = { 

    // Omitted code 

    send: function (service, method, data, callback) { 
     var url, 
      json_data = {}, 
      that = this; 
     if (this.opt_friendlyURL) { 
      url = this.opt_folder + service + '/' + method; 
     } else { 
      url = this.opt_folder + 'gateway.php?c=' + service + '&m=' + method; 
     } 
     if (data != undefined) { 
      json_data = JSON.stringify(data); 
     } 
     this.callback_function = (callback == undefined) ? null : callback; 
     $.ajax({ 
      method: 'POST', 
      url: url, 
      data: {data: json_data}, 
      success: function(data, textStatus, jqXHR) { 
       that.ajax_success(data, textStatus, jqXHR); 
      }, 
      error: function(jqXHR, textStatus, errorThrown) { 
       that.ajax_error(jqXHR, textStatus, errorThrown); 
      } 
     }); 
    }, 

    ajax_success: function (data, textStatus, jqXHR) { 
     if (this.callback_function != null) { 
      this.callback_function(true, data.data); 
     } 
    }, 

    ajax_error: function (jqXHR, textStatus, errorThrown) { 
     this.callback_function.call(false, {}); 
    } 

}; 

Теперь это работает !!!

+4

Это, кажется, работает отлично для меня. Является ли этот код посреди другого кода? –

+0

Да, это прекрасно работает. Ваша проблема в другом месте. Что касается «наилучшего способа», то это основано на мнениях. –

+0

Это должно работать нормально. Возможно, вы используете метод какого-либо другого объекта как 'myCallbackFunction', и он вызывает подобную ошибку при вызове, но не тот же? (Или, может быть, это тот же самый, и вы на самом деле делаете какую-то рекурсивную вещь?) – Ryan

ответ

1

Вот ваша проблема:

$.ajax({ 
    method: 'POST', 
    url: url, 
    data: {data: json_data}, 
    success: this.ajax_success, 
    error: this.ajax_error 
}); 

При установке success и error методам на this, они не держат их this. Когда функция JavaScript вызывается, он получает привязал this:

someFunction(); // this is undefined or the global object, depending on strict 
someObject.someFunction(); // this is someObject 

Встроенный .call, .apply и .bind из Function объектов поможет вам изменить это.

В вашем случае, я думаю, что jQuery привязывает this к объекту Ajax - хорошая причина как для использования jQuery, так и для использования строгого режима.

Если вы можете гарантировать или поддерживать прокладку ES5, bind легко исправить:

что эквивалентно этому, если вы не можете:

var that = this; 

$.ajax({ 
    method: 'POST', 
    url: url, 
    data: {data: json_data}, 
    success: function() { 
     that.ajax_success.apply(that, arguments); 
    }, 
    error: function() { 
     that.ajax_error.apply(that, arguments); 
    } 
}); 

И теперь, наконечник для вы: не занимаете пространство имен, и если вы это сделаете, не используйте this. this отлично подходит для объектов, предназначенных для строительства. Что было бы более уместным, так это, если вам действительно нужно:

var PHPGateway = (function() { 
    var callbackFunction; 
    var options = { 
     friendlyURL: true, 
     … 
    }; 
    … 

    function send(service, method, data, callback) { 
     … 
    } 
    … 

    return { send: send }; 
})(); 
+0

Спасибо, что нашли время, чтобы ответить на этот вопрос, вы были очень полезны. Основываясь на вашем ответе, я обновил код и теперь работает. Полный код не подходит для этого комментария, я обновил свой вопрос, чтобы показать окончательный код. И спасибо за отзыв, я не понимаю, что возвращает линия {send: send}, для чего это нужно? – Gonzalingui

+1

@GonzaloMassa: Идея состоит в том, что вы не создаете объект, который хранит вещи в вашем пространстве имен до самого конца, поэтому все функции являются частью области для простого доступа, а не внутри другого объекта. Но вам все равно нужно разоблачить его, и эта часть раскрывает его так же, как вы изначально имели все. – Ryan

+0

Итак, я должен добавить ** useFriendlyURL ** и ** setFolder ** на возвращаемый объект? Обе функции должны быть вызваны извне. – Gonzalingui

2

В вашем запросе $.Ajax, вам нужно добавить context вариант:

$.ajax({ 
    method: 'POST', 
    url: url, 
    data: {data: json_data}, 
    context: this, 
    success: this.ajax_success, 
    error: this.ajax_error 
}); 

Ваш this переменную в вашем успехе и ошибок обработчиков Ajax не указывает на объект, вы думаете, какие они есть. Опция context для $ .ajax() устанавливает объект this в обратные вызовы Ajax.

+0

Грег, спасибо за ваш ответ. Ваш метод проще, но ответ Minitech помог мне понять проблему __scope__, даже если я не использую jQuery. Хотел бы я отметить оба вопроса, как принято. – Gonzalingui

+1

Хех, уп! Хороший ответ. – Ryan

+1

@Gonzalo Massa: Нет проблем. :) Рад, что смог помочь. –

Смежные вопросы