使用取消方法增强 ES6 Promise
Augment ES6 Promise with cancel method
我正在尝试编写一些代码,在启动一些可能较长的 运行 异步 activity 之后,returns ES6 promise。但是,我希望能够取消 activity,所以我想用 'cancel' 方法来增强我的 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只是设置了一个定时器来模拟长运行异步activity.
这是我在 运行 时得到的:
$ 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 原生承诺来实现这一点。
我正在使用 node.js 0.12,尽管我希望它也能在当前的浏览器中工作。
问题是对 then
的调用将 return 一个新的 promise 对象,因此您将丢失对使用 cancel 方法的 promise 的引用。
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);
t.then(function(res) {
console.log("Result is ", res);
});
t.cancel();
除了 Arun 的回答之外,您还可以很容易地解决 reject
不在范围内的问题,通过引用我在范围内:
var timer;
var reject;
var p = new Promise(
function(resolve, _reject) {
reject = _reject;
timer = setTimeout(
function() {
resolve(true);
},
timeInterval
);
}
);
p.cancel = function() {
clearTimeout(timer);
reject(new Error("Request Cancelled"));
};
我不明白为什么你需要考虑 "cancelling" 承诺。相反,您可以考虑提供一个接口来 拒绝 它。你不需要担心取消计时器,因为如果承诺已经被手动拒绝,那么即使计时器关闭并调用 resolve
,它也没有任何效果。
function TimerPromise(timeInterval) {
var _reject;
var p = new Promise(function(resolve, reject) {
// Remember reject callback in outside scope.
_reject = reject;
setTimeout(() => resolve(true), timeInterval);
});
// Attach reject callback to promise to let it be invocable from outside.
p.reject= _reject();
return p;
}
然而,即使在您这样做之后,您也无法取消下游承诺的上游承诺,因为下游承诺不知道它的上游是什么。您必须这样做:
var t1 = TimerPromise(2000);
var t2 = t1.then(function(res) { console.log("Result is ", res); });
t1.reject();
"cancel" 与 promises 相关的术语具有不同的、更复杂的含义,我将不在此赘述。一些图书馆提供该功能;原生 promises 不会,尽管正在讨论将它们添加到 ES 的未来版本中。
我正在尝试编写一些代码,在启动一些可能较长的 运行 异步 activity 之后,returns ES6 promise。但是,我希望能够取消 activity,所以我想用 'cancel' 方法来增强我的 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只是设置了一个定时器来模拟长运行异步activity.
这是我在 运行 时得到的:
$ 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 原生承诺来实现这一点。
我正在使用 node.js 0.12,尽管我希望它也能在当前的浏览器中工作。
问题是对 then
的调用将 return 一个新的 promise 对象,因此您将丢失对使用 cancel 方法的 promise 的引用。
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);
t.then(function(res) {
console.log("Result is ", res);
});
t.cancel();
除了 Arun 的回答之外,您还可以很容易地解决 reject
不在范围内的问题,通过引用我在范围内:
var timer;
var reject;
var p = new Promise(
function(resolve, _reject) {
reject = _reject;
timer = setTimeout(
function() {
resolve(true);
},
timeInterval
);
}
);
p.cancel = function() {
clearTimeout(timer);
reject(new Error("Request Cancelled"));
};
我不明白为什么你需要考虑 "cancelling" 承诺。相反,您可以考虑提供一个接口来 拒绝 它。你不需要担心取消计时器,因为如果承诺已经被手动拒绝,那么即使计时器关闭并调用 resolve
,它也没有任何效果。
function TimerPromise(timeInterval) {
var _reject;
var p = new Promise(function(resolve, reject) {
// Remember reject callback in outside scope.
_reject = reject;
setTimeout(() => resolve(true), timeInterval);
});
// Attach reject callback to promise to let it be invocable from outside.
p.reject= _reject();
return p;
}
然而,即使在您这样做之后,您也无法取消下游承诺的上游承诺,因为下游承诺不知道它的上游是什么。您必须这样做:
var t1 = TimerPromise(2000);
var t2 = t1.then(function(res) { console.log("Result is ", res); });
t1.reject();
"cancel" 与 promises 相关的术语具有不同的、更复杂的含义,我将不在此赘述。一些图书馆提供该功能;原生 promises 不会,尽管正在讨论将它们添加到 ES 的未来版本中。