javascript - Using a promise to implement a timeout - throw an error - Stack Overflow

I'm trying to implement a timeout for an asynchronous function using a promise and setTimeout. I w

I'm trying to implement a timeout for an asynchronous function using a promise and setTimeout. I want to run an asynchronous operation, and if it doesn't plete by a certain amount of time, throw an error. Currently, this is what I have: (some of it found on stackoverflow)

function someOperation(cb) {
  setTimeout(function() {
    cb(null, 'Done');
  }, 2000);
}


var p = new Promise(function(resolve, reject) {
  setTimeout(function() {
    reject(new Error('Operation timed out'));
  }, 100);

  someOperation(function(err, res) {
    if (err) reject(err);
    else resolve(res);
  });

});

p.then(function(res) {
  console.log(res);
}, function(err) {
  console.log("Throwing error...")
  throw err;
});

But the program doesn't stop when the error is thrown. Would anybody be able to tell me why, and if there is an easier way to do this? I'd be very much appreciative.

EDIT: Now trying to use bluebird for the first time and it is giving someOperationPromised.timeout is not a function. Am I doing this correctly?

var Promise = require("bluebird");

function someOperation(cb) {
  setTimeout(function() {
    cb('', 'Done');
  }, 2000);
}

var someOperationPromised = Promise.promisify(someOperation);

someOperationPromised.timeout(1).then(function (){
  console.log("Finished!");
}).catch(Promise.TimeoutError, function (err) {
  throw err;
});

I'm trying to implement a timeout for an asynchronous function using a promise and setTimeout. I want to run an asynchronous operation, and if it doesn't plete by a certain amount of time, throw an error. Currently, this is what I have: (some of it found on stackoverflow)

function someOperation(cb) {
  setTimeout(function() {
    cb(null, 'Done');
  }, 2000);
}


var p = new Promise(function(resolve, reject) {
  setTimeout(function() {
    reject(new Error('Operation timed out'));
  }, 100);

  someOperation(function(err, res) {
    if (err) reject(err);
    else resolve(res);
  });

});

p.then(function(res) {
  console.log(res);
}, function(err) {
  console.log("Throwing error...")
  throw err;
});

But the program doesn't stop when the error is thrown. Would anybody be able to tell me why, and if there is an easier way to do this? I'd be very much appreciative.

EDIT: Now trying to use bluebird for the first time and it is giving someOperationPromised.timeout is not a function. Am I doing this correctly?

var Promise = require("bluebird");

function someOperation(cb) {
  setTimeout(function() {
    cb('', 'Done');
  }, 2000);
}

var someOperationPromised = Promise.promisify(someOperation);

someOperationPromised.timeout(1).then(function (){
  console.log("Finished!");
}).catch(Promise.TimeoutError, function (err) {
  throw err;
});
Share Improve this question edited Aug 3, 2016 at 2:11 Bergi 667k161 gold badges1k silver badges1.5k bronze badges asked Aug 2, 2016 at 21:39 ChaseChase 712 silver badges6 bronze badges 3
  • 1 "the program doesn't stop" - what do you mean by that? Do you expect the 2 second operation to be cancelled? No, you'll have to do that explicitly. – Bergi Commented Aug 3, 2016 at 2:11
  • 1 You have to actually call someOperationPromised() with the parens after it. – jfriend00 Commented Aug 3, 2016 at 4:25
  • " "the program doesn't stop" - what do you mean by that? " is a very snappy question. Once the [[PromiseStatus]] is set as rejected the resolutions ing after that wont have any effect on the promise status. At the meantime your someOperation function will run however since you are expected to resolve it's result and consume it at the then stage's onfulfillment calback, it will result nothing because the onfulfillment callback will not be called. This is how things get cancelled in promises. – Redu Commented Aug 3, 2016 at 9:57
Add a ment  | 

1 Answer 1

Reset to default 4

Not sure what promise library you're using, if any. May I suggest Bluebird? It's faster than native and has a lot of great features. Among them? Timeout.

From the documentation:

var Promise = require("bluebird");
var fs = Promise.promisifyAll(require('fs'));
fs.readFileAsync("huge-file.txt").timeout(100).then(function(fileContents) {

}).catch(Promise.TimeoutError, function(e) {
    console.log("could not read file within 100ms");
});

Edit:

Hey there! I took some time sorting through this, trying to figure out why your edit didn't work. My goal is to prove to you that .timeout() works. Moreover, I would like to provide you with a workable solution you can use moving forward with Bluebird.

Below I include a function I've named takesFourSeconds. It returns a promise that will resolve after 4 seconds. I then call takesFourSeconds twice. The first time I use timeout to force the promise chain to reject if it takes more than 3 seconds. The second time I force it to reject if it takes longer than 5 seconds.

var Promise = require("bluebird");

function takesFourSeconds (){
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            return resolve('hi');
        }, 4000);
    });
}

takesFourSeconds().timeout(3000).then(function(res) {
    console.log(res);
}).catch(Promise.TimeoutError, function(e) {
    console.log("promise took longer than 3 seconds");
});

takesFourSeconds().timeout(5000).then(function(res) {
    console.log(res);
}).catch(Promise.TimeoutError, function(e) {
    console.log("promise took longer than 5 seconds");
});

Note that this returns:

$ node index.js
promise took longer than 3 seconds
hi

As expected.

Small side note:

When creating a function that returns a promise, you don't have to create a new promise for every function you call in a chain of promises. Only the first function.

For example, if I wanted to call another function after takesFourSeconds() I could write it like this:

function myFunc(result){
  return result === 'hi' ? resolve('hey there') : reject('hi there');
}

then:

takesFourSeconds()
  .then(myFunc) // myFunc will take in the resolved value of takesFourSeconds implicitly
  .then(result => console.log(result)
  .catch(error => console.log(error);

This should output:

"hey there"

There you have it! Timeouts in Bluebird.js. :)

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745047237a4608173.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信