Задать вопрос
Sanu0074
@Sanu0074

Почему this не доступен в callback?

Делаю класс для пагинации, использую внутри него обертку для jquery - класс Request. Метод getRecords - это коллбэк который вешается на $(window).scroll(), внутри себя он вызывает класс Request чтобы сделать запрос, внутри которого onRequest - это коллбек success который вызывает $.ajax(). Внутри onRequest в this уже не содержится Pagination а содержится объект содержащий данные запроса.

export class Pagination{

    constructor (params? :Object){
        //.. more actions
        this.getRecords();
        fn.setOnWindowListener('scroll','pagination',null,(e) => {this.setScrollEvent(e)});
    }

    private setScrollEvent = (e) :void =>{
        let pos = $(e.currentTarget).scrollTop() + this.paginationHeight;
        let height = $(document).height();
        if(pos >= height && !this.doRequest) this.getRecords();
    };

    public getRecords = () :void =>{
        this.doRequest = true;
        //здесь this - ссылка на Pagination
        return new Request({
            url: this.url + this.currentPage,
            type: `GET`,
            dataType: this.requestDataType,
            onRequest: (data) =>{
                //а здесь this превратился в объект $.ajax()
                this.doRequest = false;
                this.currentPage++;
                this.onRecordsLoaded(data);
            }
        }).exec();
    };

}

Вопрос в том, как прокинуть this из Pagination в onRequest так чтобы внутри onRequest были доступны св-ва Pagination?

p.s.

конечно можно перед new Request() создать переменную вроде var _self = this; и дальше уже в onRequest дергать ее, но это уже будет костыль тянущий подход использующийся в es5. Это не вариант, т.к. хочется сделать все красиво.

p.p.s.

Пока сделал таким образом передачу контекста, передавая this в getRecords,
public getRecords = (context: Pagination) :void =>{
        context.doRequest = true;
        return new Request({
            url: context.url + context.currentPage,
            type: `GET`,
            dataType: context.requestDataType,
            onRequest: (data) =>{
                context.doRequest = false;
                context.currentPage++;
                context.onRecordsLoaded(context.context, data);
            }
        }).exec();
    };


И в конструкторе таким же способом запоминать контекст класса из которого был создан инстанс Pagination:
constructor (context :Object, params? :Object){
        this.context = context;
  • Вопрос задан
  • 229 просмотров
Подписаться 1 Оценить 1 комментарий
Пригласить эксперта
Ответы на вопрос 4
Ошибка - в Request. Там, видимо, onRequest передаётся в $.ajax напрямую, как-то так:
$.ajax({
  url: this.url + this.currentPage,
  type: `GET`,
  /*... more params */
}).done(this.onRequest);

Естественно, $.ajax переписывает this.
Надо как-то так:
$.ajax({
  url: this.url + this.currentPage,
  type: `GET`,
  /*... more params */
}).done(data => this.onRequest(data))
Ответ написан
Bowen
@Bowen
Японский бог
Попробуйте вынести Request в отдельном методе, например:
public ajax = (params) => new Request(params);
this.ajax({
           url: this.url + this.currentPage,
            type: `GET`,
            dataType: this.requestDataType,
            onRequest: (data) =>{
                //а здесь this превратился в объект $.ajax()
                this.doRequest = false;
                this.currentPage++;
                this.onRecordsLoaded(data);
            }
})
Ответ написан
Methos
@Methos
Применяйте .bind(this)
Ответ написан
В вашем примере #onRequest вызывается в контексте $.ajax и стрелочная функция тут не поможет. А вообще глянуть бы на реализацию Request
private _requestSuccess(data) =>{
        this.doRequest = false;
        this.currentPage++;
        this.onRecordsLoaded(data);
}

public getRecords = () :void =>{
        this.doRequest = true;
        //здесь this - ссылка на Pagination
        return new Request({
            url: this.url + this.currentPage,
            type: `GET`,
            dataType: this.requestDataType,
            onRequest: this._requestSuccess.bind(this)
        }).exec();
    };
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы