Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Promise/A+ test case (https://javascript.ru/forum/misc/52614-promise-test-case.html)

Octane 26.12.2014 19:02

Promise/A+ test case
 
не могу понять такой test case:
Код:

2.3.3: Otherwise, if `x` is an object or function,

2.3.3.3: If `then` is a function, call it with `x` as `this`,
first argument `resolvePromise`, and second argument `rejectPromise`

2.3.3.3.1: If/when `resolvePromise` is called with value `y`, run `[[Resolve]](promise, y)`

`y` is a thenable for a thenable

`y` is a thenable that tries to fulfill twice for a synchronously-fulfilled custom thenable

`then` calls `resolvePromise` synchronously via return from a fulfilled promise

что такое `y` is a thenable for a thenable?

thenable-объект понятно
var y = { 
    then: function (…) { 
        … 
    } 
};

а как будет выглядеть "a thenable for a thenable"?! :D

по описанию тест кейса в голове рисуется что-то типа такого:
var x = {
    then: function (resolvePromise) {
        resolvePromise(y);
    }
};

var y = {
    then: function (onFulfilled) {
        onFulfilled('y1');
        onFulfilled('y2');
    }
};

new Promise(function (resolve) {
    x.then(resolve);
}).then(function (value) {
    console.log('value =', value);
}, function (reason) {
    console.log('reason = ', reason);
});
но этот код работает без ошибок, в консоль выводится "y1"

Яростный Меч 27.12.2014 13:12

Я так понял, тут вот о чем:

var y = {
    then: function (resolvePromise) {
        console.log("y.then()");
        resolvePromise('y1');
    }
};

var x = {
    then: function (resolvePromise) {
        console.log("x.then()");
        resolvePromise(y);
    }
};

var pro = new Promise(function (resolve) {
    console.log("Promise: resolve(x);");
    resolve(x);
});

pro.then(function (value) {
    console.log('value =', value);
});


"х" - просто thenable, его в 17 строке передаем в resolve.
А "y" - thenable for a thenable, потому что его передаем в resolvePromise внутри x.then.

Передача thenable в resolve/resolvePromise приводит к тому, что у этих объектов вызывается then, чтобы узнать итоговое значение всего промиса (в то время как не-thenable объект сам пошел бы в качестве значения. Т.е. в итоговое значение промиса никак нельзя передать объект с методом then).


И вот тут обнаружилось разное поведение в Хроме и Fx, которое видно, если pro.then поместить в setTimeout:
Fx "прокручивает" все then во время resolve промиса (строка 17), а Хром - в момент вызова pro.then.

Кто из них прав, я понять так и не смог.

Octane 27.12.2014 15:34

странно, resolver по спецификации синхронный, в Chrome 41 вроде так же как в Firefox

еще вот такую штуку нашел http://modernjavascript.blogspot.ru/...c-through.html слайд №18

все равно не пойму на чем в этом тесте фейлится мой велосипед, вот тут https://github.com/getify/native-promise-only/issues/5 выяснили, что then всегда должен быть асинхронным…

Octane 29.12.2014 17:42

Пофиксил вот такой случай:
var testValue = 'test value';
var testReason = new Error('test error');
var thenable = {
    then: function (resolvePromise, rejectPromise) {
        resolvePromise(testValue);
        reject(testReason);
    }
};
var deferred = {};
var promise = new Promise(function (resolve, reject) {
    deferred.resolve = resolve;
    deferred.reject = reject;
    resolve(thenable);
});
deferred.resolve('other test value');
deferred.reject(new Error('other test error'));
promise.then(function (value) {
    console.log('value = "' + value + '"', value === testValue);
}, function (reason) {
    console.log('reason = "' + reason + '"', reason === testReason);
});

и тест 2.3.3.3 перестал фейлиться

Теперь все 872 теста пройдены :dance:


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