Javascript-форум (https://javascript.ru/forum/)
-   Оффтопик (https://javascript.ru/forum/offtopic/)
-   -   Promise и xhr.abort или ад перфекциониста :D (https://javascript.ru/forum/offtopic/50432-promise-i-xhr-abort-ili-ad-perfekcionista-d.html)

Octane 25.09.2014 23:41

Promise и xhr.abort или ад перфекциониста :D
 
вот пишем мы все реквесты на модных промисах, ну типа такого:
function request(url) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest;
        xhr.open('GET', url);
        xhr.onload = resolve;
        xhr.onerror = function () {
            reject(new Error(xhr.statusText));
        };
        xhr.send();
    });
}

все красиво и замечательно выглядит, колбэковый ад позади, ничто не предвещает беды, и тут вдруг понадобилось выполнять xhr.abort(), но как?! ведь xhr объект мы получим только после окончания загрузки, в голову приходит такое извращение:
function request(url, onBeforeSend) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest;
        xhr.open('GET', url);
        xhr.onload = resolve;
        xhr.onerror = function () {
            reject(new Error(xhr.statusText));
        };
        if (onBeforeSend) {
            onBeforeSend(xhr);
        }
        xhr.send();
    });
}

request('…', function (xhr) {
    …
    //в какой-то момент выполняем
    xhr.abort();
    …
}).then(onFulfilled, onRejected);
вся красота порушена, нет больше идеального мира :(

но это еще не все, дальше возникает вопрос, что делать после abort, выполнять onRejected или оставлять промис зависшим?

nerv_ 25.09.2014 23:47

делай так, никто не запрещает
http://stackoverflow.com/a/17328336
вообщем возвращай расширенный промис (например)

у меня спец объект для работы с серваком =) Выглядит примерно так

var server = new Server(methods);

server.addMethods({
    // ...
    getProfile: {
        method: 'POST',
        url: '/demo/api/grants/get_profile.php'
    },
    saveProfile: {
        method: 'POST',
        url: '/demo/api/grants/save_profile.php'
    }
    // ...
});

// server.getProfile(query).success().error().then()...

// абортить можно, например, так
server.getProfile.cancel();

// пофантазируй =)

Octane 26.09.2014 00:06

да, здесь как раз пригодится поддержка thenable value, из requestа буду возвращать не настоящий промис, а объект с методоми then и cancel, не, не прокатит
жаль наследовать от промиса нельзя

кстати Promise.cancel :)

nerv_ 26.09.2014 00:16

еще вариант
function request(url) {
    var promise = new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest;
        xhr.open('GET', url);
        xhr.onload = resolve;
        xhr.onerror = function () {
            reject(new Error(xhr.statusText));
        };
        xhr.send();
        promise.abort = xhr.abort;
    });
    promise.abort = noop;
    return promise;
}

promise.abort();


ну, т.е. крути как тебе надо)

l-liava-l 26.09.2014 00:51

Octane,
nerv_,
Я не понимаю, вы просто играетесь или юзаете полифилы? Или на es6 в продакшен?

Octane 26.09.2014 00:54

наверное, лучше сразу сделать метод getXHR
promise.getXHR().abort();


свой вариант я упростил, в реальности же там объект с параметрами, поэтому onBeforeSend не так страшно смотрится

Octane 26.09.2014 00:59

Цитата:

Сообщение от l-liava-l
Я не понимаю, вы просто играетесь или юзаете полифилы? Или на es6 в продакшен?

Promise уже в stable версиях Firefox, Chrome и Safari, и прекрасно полифилится, почему бы не юзать прямо сейчас?

l-liava-l 26.09.2014 01:09

Цитата:

Promise уже в stable версиях Firefox, Chrome и Safari, и прекрасно полифилится, почему бы не юзать прямо сейчас?
Просто я упустил момент ;)

Octane 26.09.2014 10:59

Так а чо какие мнения по поводу abort, это же не ошибка, всеравно реджектить?
стандартный onerror не срабатывает при abort

melky 26.09.2014 11:01

Octane, throw new Error вызовет reject внутри полифила?


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