Я пытаюсь написать код, который возвращает обещание ES6 после запуска некоторой потенциально длительной асинхронной активности. Однако я хотел бы иметь возможность отменить это действие, поэтому я хочу дополнить свое обещание методом «отмены».
sscce, который иллюстрирует то, что я пытаюсь сделать, выглядит следующим образом:
function TimerPromise(timeInterval) {
var timer;
var p = new Promise(
function(resolve,reject) {
timer = setTimeout(
function() {
resolve(true);
},
timeInterval
);
}
);
p.cancel = function() {
clearTimeout(timer);
};
console.log("p.cancel is ",p.cancel);
return p;
}
var t = TimerPromise(2000).then(function(res) { console.log("Result is ",res); });
t.cancel();
В примере TimerPromise просто устанавливает таймер для имитации длительной асинхронной активности.
Вот что я получаю при запуске:
$ node test.js
p.cancel is function () {
timer.clearTimeout();
}
/home/harmic/js/src/test.js:28
t.cancel();
^
TypeError: t.cancel is not a function
at Object.<anonymous> (/home/harmic/js/src/test.js:28:3)
at Module._compile (module.js:413:34)
at Object.Module._extensions..js (module.js:422:10)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Function.Module.runMain (module.js:447:10)
at startup (node.js:141:18)
at node.js:933:3
По какой-то причине метод отмены, который я добавил в обещание, исчез после выхода из функции!
Есть ли какая-то причина, по которой я не могу добавлять свойства или методы в обещание ES6? Или это какая-то особенность реализации Promises в V8?
Для бонусных баллов - я хотел бы иметь возможность отклонить обещание, если вызывается метод отмены, что-то вроде этого:
p.cancel = function() {
timer.clearTimeout();
reject(new Error("Request Cancelled"));
};
Однако я не могу получить доступ к функции отклонения вне исполнителя обещания, а внутри исполнителя обещания я не могу получить доступ к самому обещанию (или могу?), поэтому я не могу увеличить обещание внутри него.
Есть ли разумный шаблон для этого?
Примечание. Мне известно, что Bluebird предоставляет отменяемые обещания в качестве расширения. Я надеялся реализовать это с помощью собственных промисов ES6.
Я использую node.js 0.12, хотя я бы хотел, чтобы это работало и в текущих браузерах.
TimerPromise(2000).cancel()
напрямую, но затем вернете новый собственный промис. - person Paul   schedule 04.03.2016then
и добавивfinally
. Я опубликую ответ когда-нибудь. - person Benjamin Gruenbaum   schedule 04.03.2016