Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Замыкание как аякс функция и ее данные (https://javascript.ru/forum/misc/56244-zamykanie-kak-ayaks-funkciya-i-ee-dannye.html)

Zalex 06.06.2015 15:16

Замыкание как аякс функция и ее данные
 
На самом деле я сомневаюсь что заголовок соответствует теме, но все таки...

Здравствуйте. Попробую объяснить Вам свою проблему, возможно Вы найдете возможным ответить.

1. Сущствует объект, который получает данные аяксом.

Здесь мы видим что в rawdata мы получаем результат, который быть может либо promise либо другое, что не имеет отношения к вопросу...

Вот часть кода

var rawdata = this.request(), that = this;
     $.when(rawdata).then(function () {
        if(rawdata.hasOwnProperty('responseText')) {
            try {
                var json = $.parseJSON(rawdata.responseText);
            } //... и дальше по списку



2.
Здесь мы видим что тот самый this.request мы получаем через другой метод

Stat.prototype.setRequest = function(request) {
    try {
        this.request = request.getAjaxFunction();
    }
    catch (err) {
        console.log('Не аякс'); //И так далее


3. И вот подходим к самому значению request - это возвращаемая объектом с методом getAjaxFunction() ,функция jquery ajax
CompositeAjaxRequest.prototype.getAjaxFunction = function () {
    var that = this;
    return function () {
        var self = this; //self - контекст вызывающего результирующую функцию объекта
        self.sentdata['sourceid'] = self.source.getId();
        return $.ajax({
            url: that.url,
            data: self.sentdata,
            type: 'POST'
        })
    };
};


Пишу так подробно, чтоб стало понятно, когда осуществляется вызов
var rawdata = this.request()
, то this результирующей функции указывает на контекст вызывавшего его объекта, в моем случае назову его Comments.

Вот я и подобрался к задаче, которую я решить не могу. Итак - rawdata вызывает this.request() объектом Comments каждый раз, когда ему нужно обновится. this.request же в свою очередь содержит при каждом вызове нижеприведенную функцию (в случае если не очень понятно что я нагородил )

(function () {
        var self = this; //self - контекст вызывающего результирующую функцию объекта
        self.sentdata['sourceid'] = self.source.getId();
        return $.ajax({
            url: that.url, //that - контекст объекта  "хозяина" метода
            data: self.sentdata,
            type: 'POST'
        })
    })


Итак, мы видим что self.sentdata - это по сути объект, который посылается как данные по аяксу и в силу того что функция эта вызывается в контексте вызывающего объекта Comments, значит self.sentdata в моем случае берется из объекта Comments, который вызывает функцию (закрутил, не правда ли ? :)) )

Т.е. что я ожидаю ? А ожидаю я при каждом выполнении этой аякс функции - отсыл данных по аяксу, а данные живут в sentdata объекта Comments(мы же помним что именно он вызывает в итоге выполнение). Вот и посмотрим на эти данные
(тут часть кода , на лишнее внимание не обращаем)
function Comments() {
    Stat.call(this);
    this.page = 1;
    this.sentdata = {
        action: 'getComments',
        page: this.page
    };
}


И действительно я вижу, что все ключи и значения sentdata объекта Comments появляются, живут и отсылаются,
Параметрыapplication/x-www-form-urlencodedНе сортировать
action	getComments
page	1
sourceid	1
Исходный код
action=getComments&page=1&sourceid=1


НО! (барабаны бъют), при изменении состояния объекта Comments, например изменилось значение page, я все равно получаю в отсылаемых данных - 1(единицу), т.е. то что было при инициализации объекта!
И что самое в этом прекрасное, что если я пишу код например вот так -

CompositeAjaxRequest.prototype.getAjaxFunction = function () {
    var that = this;
    return function () {
        var self = this; //self - контекст вызывающего результирующую функцию объекта
        self.sentdata['sourceid'] = self.source.getId();
        self.sentdata['page'] = self.page;
        return $.ajax({
            url: that.url,
            data: self.sentdata,
            type: 'POST'
        })
    };
};


Обратите внимание - self.sentdata['page'] = self.page;
(на всякий случай еще раз напомню что self в данном случае это контекст объекта Comments, который вызывает функцию)
я убираю page из sentdata объекта Comments и и добавляю в функцию перед return $.ajax этот код
self.sentdata['page'] = self.page;

и у меня, о чудо, все работает! Т.е. при изменении page в объекте Commentsя получаю в аяксе page который на данный момент актуален.

Простите за долгую историю, а вопрос краток - почему происходит именно так ? Я понимаю что тут мелочная мелочь, о которой я забыл или попросту не знаю и нужно просто правильно вызывать перед функцией аяксовой мой объект с передаваемыми данными , но я не соображу как именно.

Благодарю.

upd. Посидев, подумав, пришел к тому выводу, что нужно сделать вот что

Переделываем
this.sentdata = {
        action: 'getComments',
        page: this.page
    };

Приводим к такому виду
this.sentdata = function (context)
    {
        return {
            action: 'getComments',
            page: context.page
        };
    };


Тогда функция возвращаемая мне аякс будет выглядеть так
CompositeAjaxRequest.prototype.getAjaxFunction = function () {
    var that = this;
    return function () {
        var self = this; //self - контекст вызывающего результирующую функцию объекта
        var datatoajax = {};
        $.extend(datatoajax, self.sentdata(self));
        datatoajax['sourceid'] = self.source.getId();
        return $.ajax({
            url: that.url,
            data: datatoajax,
            type: 'POST'
        })
    };
};


Вот эта строчка выглядит немного каламбуристо :)
$.extend(datatoajax, self.sentdata(self));
Но так или иначе это работает. Получается что я добиваюсь того, чего хотел - а именно я могу "мерджить" нужные мне данные.

Задача в общем и целом решена, но все -таки возможно кто то имеет опыт в более правильном коде, как решаются подобные задачи.


Часовой пояс GMT +3, время: 06:05.