Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 26.12.2014, 19:02
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

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"?!

по описанию тест кейса в голове рисуется что-то типа такого:
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"
Ответить с цитированием
  #2 (permalink)  
Старый 27.12.2014, 13:12
Профессор
Отправить личное сообщение для Яростный Меч Посмотреть профиль Найти все сообщения от Яростный Меч
 
Регистрация: 12.04.2010
Сообщений: 557

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

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.

Кто из них прав, я понять так и не смог.
Ответить с цитированием
  #3 (permalink)  
Старый 27.12.2014, 15:34
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

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

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

все равно не пойму на чем в этом тесте фейлится мой велосипед, вот тут https://github.com/getify/native-promise-only/issues/5 выяснили, что then всегда должен быть асинхронным…
Ответить с цитированием
  #4 (permalink)  
Старый 29.12.2014, 17:42
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Пофиксил вот такой случай:
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 теста пройдены
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Unexpected token M yriiarutiunian Общие вопросы Javascript 4 19.11.2014 11:14
Как и где задать цикл? Blondinka Events/DOM/Window 2 10.06.2014 15:29
onResize() для DIV-a faiwer Общие вопросы Javascript 6 26.06.2012 15:27
Расшифровка кода, генерируемого flash. ГостьФорума Общие вопросы Javascript 6 02.02.2011 01:26
Не работает скрипт Ling Firefox/Mozilla 2 03.05.2009 16:03