【发布时间】:2016-06-17 21:09:49
【问题描述】:
我正在尝试编写一些代码,在启动一些可能长时间运行的异步活动后返回一个 ES6 承诺。但是,我希望能够取消该活动,因此我想使用“取消”方法来增加我的 Promise。
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
由于某种原因,我在promise中添加的cancel方法在离开函数后消失了!
我不能向 ES6 Promise 添加属性或方法有什么原因吗?或者这是 Promises V8 实现的一些特殊性?
对于奖励积分 - 如果调用取消方法,我希望能够拒绝承诺,如下所示:
p.cancel = function() {
timer.clearTimeout();
reject(new Error("Request Cancelled"));
};
但是,我无法在 Promise 执行器之外访问拒绝函数,在 Promise 执行器内部我无法访问 Promise 本身(或者我可以吗?),因此我无法在其中增加 Promise。
这样做有什么合理的模式吗?
注意:我知道Bluebird 提供了可取消的承诺作为扩展。我希望使用 ES6 原生 Promise 来实现这一点。
我使用的是 node.js 0.12,尽管我希望它也能在当前的浏览器中工作。
【问题讨论】:
-
你可以像往常一样增加promise,你会看到你可以直接调用
TimerPromise(2000).cancel(),然后返回一个新的native Promise。 -
你的 polyfill 不好——你想要第三状态取消语义,因为异常语义不正确。没有一个答案提供了我建议使用的东西 - 相反,您希望继承常规承诺并通过覆盖
then并添加finally来为它们提供该功能。我会在某个时候发布答案。
标签: javascript node.js promise es6-promise cancellation