return new Promise(function(resolve, reject {
const to = setTimeout(function(){
});
});
想象一下,我想确保从执行器函数内部清理资源。
我想做这样的事情:
return new Promise(function(resolve, reject {
const to = setTimeout(function(){
});
this.finally(function(){
clearTimeout(to);
});
});
但this
在promise执行函数中不可用。
有没有办法在promise执行器中清理异步资源?
我想你可以在致电解决/拒绝之前清理它们,但有一些情况会更难。
答案 0 :(得分:1)
不确定是否需要在触发后清除超时但您可以尝试以下操作:
var someTest = () => {
var t;
var p = new Promise(
(resole)=>{
t = setTimeout(resole,2000)
}
);
p.finally(
()=>console.log(t,clearTimeout(t))
)
return p;
}
someTest();
或者您可以尝试以下方法:
var someTest = () =>
new Promise(
(resole)=>{
t = setTimeout(resole,2000)
}
).then(
result=>{
//clean up
return result
},
error=>{
//clean up
return Promise.reject(error)
}
);
答案 1 :(得分:1)
从承诺执行者内部,您无法访问承诺。尚未将其分配给您的代码可以访问的任何内容。
所以,你有两个选择。
p.finally()
访问返回的承诺。然后,您还必须在执行者之外跟踪您的资源(这可能不方便)。resolve()
和reject()
回调,然后调用实际的resolve()
或reject()
。p.finally()
和resolve()
以及reject()
(这真是原始挑战的源头。)以下是选项#2的示例:
return new Promise(function(rv, rj) {
// have to try/catch here because an execption will automatically reject
// without us having seen it
try {
// declare wrappers that should be called by code in this executor
// do not call rv() and rj() directly
function resolve(arg) {
finally();
rv(arg);
}
function reject(arg) {
finally();
rj(arg);
}
// cleanup code that is only ever called once
let finallyCalled = false;
function finally() {
if (!finallyCalled) {
clearTimeout(to);
finallyCalled = true;
}
}
const to = setTimeout(function(){
});
// elsewhere in this executor it should call resolve() or reject()
} catch(e) {
reject(e);
}
});
以下是选项#3的示例。
通常不建议使用延迟对象,但它们确实允许您访问.finally()
,resolve()
和reject()
所有相同的范围,这样可以使某些内容更清晰(就像您所做的那样)重新尝试)。
首先是一个简单的promise包装器,它为我们提供了一个Deferred对象:
// can be used as either:
// let d = Promise.Deferred();
// let d = new Promise.Deferred();
// d.then(...)
// d.resolve(x);
// d.finally(...)
Promise.Deferred = function() {
if (!(this instanceof Promise.Deferred)) {
return new Promise.Deferred();
}
let p = this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
this.then = p.then.bind(p);
this.catch = p.catch.bind(p);
this.finally = p.finally.bind(p);
}
然后,您可以像这样使用它:
// usage
function yourFunction() {
let d = new Promise.Deferred();
const to = setTimeout(...);
// other code here that will call d.resolve() or d.reject()
// cleanup code
d.finally(function() {
clearTimeout(to);
});
return d.promise;
}
答案 2 :(得分:0)
这个OP用Promises imo描述了一个丑陋的snafus,但这可能有用:
return new Promise(function(resolve, reject {
const to = setTimeout(function(){
console.error('timed out');
reject('timed out');
});
doSomething(function(err, data){
if(!to._called){
resolve({to, data})
}
});
})
.then(function(v){
clearTimeout(v && v.to);
return v && v.data;
});
使用此解决方案的问题是,then中的回调称为异步,因此定时器可能会在临时解析?不确定。