Javascript 如果未能及时完成,NodeJS超时承诺
在一定时间后,我如何使承诺超时? 我知道Q有一个承诺超时,但我使用的是本机NodeJS承诺,它们没有.timeout函数 我是少了一个还是包装不同了 或者,下面的实现在不占用内存的情况下是否很好,实际工作是否如预期的那样 我还可以将它以某种方式进行全局包装,这样我就可以将它用于我创建的每个承诺,而不必重复setTimeout和clearTimeout代码Javascript 如果未能及时完成,NodeJS超时承诺,javascript,node.js,promise,settimeout,Javascript,Node.js,Promise,Settimeout,在一定时间后,我如何使承诺超时? 我知道Q有一个承诺超时,但我使用的是本机NodeJS承诺,它们没有.timeout函数 我是少了一个还是包装不同了 或者,下面的实现在不占用内存的情况下是否很好,实际工作是否如预期的那样 我还可以将它以某种方式进行全局包装,这样我就可以将它用于我创建的每个承诺,而不必重复setTimeout和clearTimeout代码 function run() { logger.info('DoNothingController working on proces
function run() {
logger.info('DoNothingController working on process id {0}...'.format(process.pid));
myPromise(4000)
.then(function() {
logger.info('Successful!');
})
.catch(function(error) {
logger.error('Failed! ' + error);
});
}
function myPromise(ms) {
return new Promise(function(resolve, reject) {
var hasValueReturned;
var promiseTimeout = setTimeout(function() {
if (!hasValueReturned) {
reject('Promise timed out after ' + ms + ' ms');
}
}, ms);
// Do something, for example for testing purposes
setTimeout(function() {
resolve();
clearTimeout(promiseTimeout);
}, ms - 2000);
});
}
谢谢 本机JavaScript承诺没有任何超时机制 关于您的实现的问题可能更适合您,但请注意:
setTimeout
回调中不需要clearTimeout
,因为setTimeout
调度一个一次性计时器
myPromise
函数方法,可能是这样的:
function myPromise(timeout, callback) {
return new Promise((resolve, reject) => {
// Set up the timeout
const timer = setTimeout(() => {
reject(new Error(`Promise timed out after ${timeout} ms`));
}, timeout);
// Set up the real work
callback(
(value) => {
clearTimeout(timer);
resolve(value);
},
(error) => {
clearTimeout(timer);
reject(error);
}
);
});
}
myPromise(2000, (resolve, reject) => {
// Real work is here
});
这样使用:
function myPromise(timeout, callback) {
return new Promise((resolve, reject) => {
// Set up the timeout
const timer = setTimeout(() => {
reject(new Error(`Promise timed out after ${timeout} ms`));
}, timeout);
// Set up the real work
callback(
(value) => {
clearTimeout(timer);
resolve(value);
},
(error) => {
clearTimeout(timer);
reject(error);
}
);
});
}
myPromise(2000, (resolve, reject) => {
// Real work is here
});
(或者可能稍微不那么复杂,请参见下面的分隔符。)
我会稍微关注语义不同的事实(没有new
,而您确实使用new
和Promise
构造函数)。但更大的问题是,它假设您总是从头开始创建承诺,但您通常希望能够使用您已经拥有的承诺
您可以通过子类化Promise
来处理这两个问题:
class MyPromise extends Promise {
constructor(timeout, callback) {
// We need to support being called with no milliseconds
// value, because the various Promise methods (`then` and
// such) correctly call the subclass constructor when
// building the new promises they return.
const haveTimeout = typeof timeout === "number";
const init = haveTimeout ? callback : timeout;
super((resolve, reject) => {
if (haveTimeout) {
const timer = setTimeout(() => {
reject(new Error(`Promise timed out after ${timeout}ms`));
}, timeout);
init(
(value) => {
clearTimeout(timer);
resolve(value);
},
(error) => {
clearTimeout(timer);
reject(error);
}
);
} else {
init(resolve, reject);
}
});
}
// Pick your own name of course. (You could even override `resolve` itself
// if you liked; just be sure to do the same arguments detection we do
// above in the constructor, since you need to support the standard use of
// `resolve`.)
static resolveWithTimeout(timeout, x) {
if (!x || typeof x.then !== "function") {
// `x` isn't a thenable, no need for the timeout,
// fulfill immediately
return this.resolve(x);
}
return new this(timeout, x.then.bind(x));
}
}
用法(如果构建新承诺):
用法(如果使用您已有的承诺):
现场示例:
“严格使用”;
类MyPromise扩展了Promise{
构造函数(超时、回调){
//我们需要支持无毫秒调用
//值,因为各种Promise方法(`then`和
//这样)在以下情况下正确调用子类构造函数
//建立他们所回报的新承诺。
const haveTimeout=typeof timeout==“number”;
const init=haveTimeout?回调:超时;
超级((解决、拒绝)=>{
if(haveTimeout){
常量计时器=设置超时(()=>{
拒绝(新错误(`Promise timeout after${timeout}ms`);
},超时);
初始化(
(值)=>{
清除超时(计时器);
决心(价值);
},
(错误)=>{
清除超时(计时器);
拒绝(错误);
}
);
}否则{
初始化(解决、拒绝);
}
});
}
//当然,选择你自己的名字。(你甚至可以覆盖'resolve'本身。)
//如果您喜欢,请确保执行与我们相同的参数检测
//在构造函数中,因为您需要支持
//‘解决`。)
静态resolveWithTimeout(超时,x){
如果(!x | | typeof x.then!=“函数”){
//'x'不是一个表,不需要超时,
//立即履行
返回此。解决(x);
}
返回新的this(超时,x.then.bind(x));
}
}
//演示的一些功能
const neverSettle=()=>新承诺(()=>{});
const fulfillAfterDelay=(延迟,值)=>newpromise((解析)=>setTimeout(解析,延迟,值));
const rejectAfterDelay=(延迟,错误)=>新承诺((解析,拒绝)=>设置超时(拒绝,延迟,错误));
常量示例=[
创建新Promise1()时的函数用法{
log(“创建新承诺时显示超时”);
const p=新承诺(100,(解决,拒绝)=>{
//我们从不解析/拒绝,所以我们测试超时
});
返回p.then((值)=>{
log(`completed:${value}`);
})
.catch((错误)=>{
log(`Rejected:${error}`);
});
},
创建新Promise2()时的函数用法{
log(“显示超时前承诺何时履行”);
const p=新承诺(100,(解决,拒绝)=>{
setTimeout(解析,50,“工作”);
});
返回p.then((值)=>{
log(`completed:${value}`);
})
.catch((错误)=>{
log(`Rejected:${error}`);
});
},
创建新Promise3()时的函数用法{
log(“显示承诺在超时之前被拒绝的时间”);
const p=新承诺(100,(解决,拒绝)=>{
setTimeout(拒绝,50,新错误(“失败”);
});
返回p.then((值)=>{
log(`completed:${value}`);
})
.catch((错误)=>{
log(`Rejected:${error}`);
});
},
函数用法(当您已准备好访问权限1时){
log(“使用我们已有的承诺时显示超时”);
返回MyPromise.resolveWithTimeout(100,neverSettle())
。然后((值)=>{
log(`completed:${value}`);
})
.catch((错误)=>{
log(`Rejected:${error}`);
});
},
函数用法(当您已准备好访问权限2时){
log(“使用我们已有的承诺时显示履行”);
返回MyPromise.resolveWithTimeout(100,fulfillAfterDelay(50,“已工作”))
。然后((值)=>{
log(`completed:${value}`);
})
.catch((错误)=>{
log(`Rejected:${error}`);
});
},
函数用法(当您已准备好访问权限3时){
log(“显示拒绝
var Promise = require('bluebird');
var p = new Promise(function(reject, resolve) { /.../ });
p.timeout(3000) //make the promise timeout after 3000 milliseconds
.then(function(data) { /handle resolved promise/ })
.catch(Promise.TimeoutError, function(error) { /handle timeout error/ })
.catch(function(error) { /handle any other non-timeout errors/ });
const withTimeout = (millis, promise) => {
const timeout = new Promise((resolve, reject) =>
setTimeout(
() => reject(`Timed out after ${millis} ms.`),
millis));
return Promise.race([
promise,
timeout
]);
};
await withTimeout(5000, doSomethingAsync());
const { TimeoutResolvePromise, TimeoutRejectPromise } = require('nodejs-promise-timeout');
const TIMEOUT_DELAY = 2000;
// This promise will reject after 2 seconds:
let promise1 = new TimeoutRejectPromise(TIMEOUT_DELAY, (resolve, reject) => {
// Do something useful here, then call resolve() or reject()
});
import {timeout} from 'utils-decorators';
class SomeService {
@timeout(3000)
doSomeAsync(): Promise<any> {
....
}
}
import {timeoutify} from 'utils-decorators';
const withTimeout = timeoutify(originalFunc, 3000);
const result = await withTimeout(() => doSomethingAsync(...args), 3000)();
const result = await withTimeout(doSomethingAsync, 3000)(...args);
const doSomethingAsyncWithTimeout = withTimeout(doSomethingAsync, 3000);
const result = await doSomethingAsyncWithTimeout(...args);
/**
* returns a new function which calls the input function and "races" the result against a promise that throws an error on timeout.
*
* the result is:
* - if your async fn takes longer than timeout ms, then an error will be thrown
* - if your async fn executes faster than timeout ms, you'll get the normal response of the fn
*
* ### usage
* ```ts
* const result = await withTimeout(() => doSomethingAsync(...args), 3000);
* ```
* or
* ```ts
* const result = await withTimeout(doSomethingAsync, 3000)(...args);
* ```
* or even
* ```ts
* const doSomethingAsyncWithTimeout = withTimeout(doSomethingAsync, 3000);
* const result = await doSomethingAsyncWithTimeout(...args);
* ```
*/
const withTimeout = <R, P extends any, T extends (...args: P[]) => Promise<R>>(logic: T, ms: number) => {
return (...args: Parameters<T>) => {
// create a promise that rejects in <ms> milliseconds; https://italonascimento.github.io/applying-a-timeout-to-your-promises/
const timeout = new Promise((resolve, reject) => {
const id = setTimeout(() => {
clearTimeout(id);
reject(new Error(`promise was timed out in ${ms} ms, by withTimeout`));
}, ms); // tslint:disable-line align
});
// returns a "race" between our timeout and the function executed with the input params
return Promise.race([
logic(...args), // the wrapped fn, executed w/ the input params
timeout, // the timeout
]) as Promise<R>;
};
};