How to cancel timeout inside of Javascript Promise?

前端 未结 4 1669
迷失自我
迷失自我 2020-12-29 06:04

I\'m toying with promises in JavaScript and tried to promisify setTimeout function:

function timeout(ms) {
  return new Promise(function(resolve, reject) {
          


        
4条回答
  •  [愿得一人]
    2020-12-29 07:04

    PSL's answer is right, however - there are a few caveats and I'd do it a bit differently.

    • A timeout being cleared means the code will not run - so we should reject the promise.
    • Returning two things isn't necessary in our case, we can monkey patch in JavaScript.

    Here:

    function timeout(ms, value) {
        var p = new Promise(function(resolve, reject) {
            p._timeout = setTimeout(function() {
                resolve(value);
            }, ms);
            p.cancel = function(err) {
                reject(err || new Error("Timeout"));
                clearTimeout(p._timeout); // We actually don't need to do this since we
                                          // rejected - but it's well mannered to do so
            };
        });
        return p;
    }
    

    Which would let us do:

    var p = timeout(1500)
    p.then(function(){
         console.log("This will never log");
    })
    
    p.catch(function(){
         console.log("This will get logged so we can now handle timeouts!")
    })
    p.cancel(Error("Timed out"));
    

    One might be interested in full blown cancellation and indeed some libraries support this directly as a feature of the library. In fact I'd dare say most do. However, this causes interference problems. Quoting KrisKowal from here:

    My position on cancellation has evolved. I am now convinced that cancellation (bg: that propagates) is inherently impossible with the Promise abstraction because promises can multiple dependess and dependees can be introduced at any time. If any dependee cancels a promise, it would be able to interfere with future dependees. There are two ways to get around the problem. One is to introduce a separate cancellation "capability", perhaps passed as an argument. The other is to introduce a new abstraction, a perhaps thenable "Task", which in exchange for requiring that each task only have one observer (one then call, ever), can be canceled without fear of interference. Tasks would support a fork() method to create a new task, allowing another dependee to retain the task or postpone cancellation.

提交回复
热议问题