javascript 在特定时间停止承诺执行

fzsnzjdm  于 2023-01-11  发布在  Java
关注(0)|答案(1)|浏览(141)
function sleep(t) {
    return new Promise((resolve, reject) =>{
        setTimeout(() => {
            console.log('timeout!')
            return resolve({isTimeout: true})
        }, t);
    });
}

function thirdPartyFunction(t) { // thirdPartyFunction can't be edited
    return new Promise((resolve, reject) =>{
        setTimeout(() => {
            console.log('thirdPartyFunction completed!')
            return resolve({success: true})
        }, t);
    });
}

function main() {
    return new Promise(async(resolve, reject) => {
        try {
            let thirdPartyFunctionExecutionTime =  Math.floor(Math.random() * 10) + 1;
            thirdPartyFunction(thirdPartyFunctionExecutionTime * 1000, false).then( (r) => {
                console.log('should not execute this if thirdPartyFunctionExecutionTime > timeout') // only goal
                // other code which is not useful after timeout
            });

            const timeout = 3;
            console.log(`thirdPartyFunctionExecutionTime: ${thirdPartyFunctionExecutionTime}, timeout - ${timeout}`)
            await sleep(timeout * 1000, true);
            throw 'stop main()'
            // return
        } catch (error) {
            console.log('in catch')
            return;
        }
    })
}

main()

超时是固定的。thirdPartyFunctionExecutionTime可能非常大(有时)在我的实际情况下,说30秒。我不希望在超时后后台运行的东西。
thirdPartyFunction承诺函数应在超时时停止执行。

e5nqia27

e5nqia271#

顺便说一句,这里有一个通用函数,可以添加一个超时,并带有取消选项。这个函数可以和任何承诺一起使用来添加一个超时。
如果promise表示的底层异步操作是可取消的,那么您可以提供一个cancel函数,如果异步操作先完成,这将自动清除计时器,使其不再继续运行。

// the main purpose of this class is so that callers can test
// to see if the reject reason is a TimeoutError vs. some other type of error
class TimeoutError extends Error {
    constructor(...args) {
        super(...args);
    }

}

// add a timeout to any promise
function addTimeout(promise, t, timeoutMsg = "timeout") {
    let timer;
    const timerPromise = new Promise((resolve, reject) => {
        timer = setTimeout(() => {
            timer = null;
            // if the promise has a .cancel() method, then call it
            if (typeof promise.cancel === "function") {
                try {
                    promise.cancel();
                } catch(e) {
                    console.log(e);
                }
            }
            reject(new TimeoutError(timeoutMsg));
        }, t)
    });
    // make sure the timer doesn't keep running if the promise finished first
    promise.finally(() => {
        if (timer) {
            clearTimeout(timer);
        }
    })
    return Promise.race([promise, timerPromise]);
}

然后,您可以在代码中使用它,如下所示:

function main() {
    addTimeout(thirdPartyFunction(...), 3000).then(result => {
        // thirdPartyFunction succeeded and timeout was not hit
        // use the result here
    }).catch(err => {
        console.log(err);
        // an error occurred here
        if (err instanceof TimeoutError) {
            // timeout
        } else {
            // other error
        }
    })
}

如果您的异步操作能够在此操作超时时取消,则可以像这样支持它:

function main() {
    let p = thirdPartyFunction(...);
    p.cancel = function () {
        // cancel the thirdPartyFunction here (depends uponn the specific operation)
    }
    addTimeout(p, 3000).then(result => {
        // thirdPartyFunction succeeded and timeout was not hit
        // use the result here
    }).catch(err => {
        console.log(err);
        // an error occurred here
        if (err instanceof TimeoutError) {
            // timeout
        } else {
            // other error
        }
    })
}

相关问题