承诺是在错误时实现的

时间:2014-03-19 19:03:24

标签: javascript error-handling promise bluebird

好吧,我以为我已经理解了Promises,但似乎我错过了这个......

var redisPromise = new Promise(function(resolve, reject) {
  redisClient.on('error', reject);
  redisClient.on('ready', resolve);
}).then(function() {
  // THIS ISN'T CALLED - CORRECT
  log.enabled && log('connected, version: %s', redisClient.server_info.redis_version);
  return redisClient;
}).catch(function() {
  // THIS GETS CALLED - CORRECT
  log('failed connecting to database:', e.message);
});

redisPromise.then(function() {
  log("This shouldn't be called when connection fails");
});

对于与Redis连接失败的情况,我希望拒绝返回的Promise。但出于某种原因,它已经实现了。我在这里错过了什么吗?

我正在使用Bluebird实施。可能是那里的一些错误吗?我有点怀疑,这一切似乎都记录得很好,并且在纸面上有意义。

分辨

https://github.com/petkaantonov/bluebird/issues/156

的完整讨论

3 个答案:

答案 0 :(得分:1)

then在某些库中创建了新的承诺。我的猜测是蓝鸟还会在catch创建一个承诺。你链接它们的方式,redisPromise指的是" catch"承诺,而不是第一个承诺。并且"赶上"确实已经解决了。

如果我是对的,这应该按预期工作:

var redisPromise = new Promise(function(resolve, reject) {
  redisClient.on('error', reject);
  redisClient.on('ready', resolve);
});

redisPromise.then(function() {
  // THIS ISN'T CALLED - CORRECT
  log.enabled && log('connected, version: %s', redisClient.server_info.redis_version);
  return redisClient;
}).catch(function() {
  // THIS GETS CALLED - CORRECT
  log('failed connecting to database:', e.message);
});

redisPromise.then(function() {
  log("This shouldn't be called when connection fails");
});

答案 1 :(得分:1)

从GH问题中复制答案,包括Domenic的代码示例:

Domenic给出了以下示例:考虑等效的同步代码:

try {
   ...
} catch (e) {
  // THIS GETS CALLED - CORRECT
  log('failed connecting to database:', e.message);
}

log('This shouldn't be called when connection fails :/');

你可以看到为什么你的期望不能很好地发挥作用。

添加到Domenic的出色模拟。 如果您想要发出执行失败的信号并处理它,您需要重新抛出:

try {
   ...
} catch (e) {
  // THIS GETS CALLED - CORRECT
  log('failed connecting to database:', e.message);
  throw e;
}

在你的情况下:

}).catch(function(e) {
  log('failed connecting to database:', e.message);
  throw e;
});

如果您想要发出异常类型的信号 - 抛出您自己的失败类型。对于可能未处理的拒绝的类比是当你输入同步代码并且不处理它时会发生什么。它默认将其记录到控制台。

这是我不喜欢的另一种解决方案:

var redisPromise = new Promise(function(resolve, reject) {
  redisClient.on('error', reject);
  redisClient.on('ready', resolve);
}).then(function() {
  log.enabled && log('connected, version: %s', redisClient.server_info.redis_version);
  return redisClient;
});
redisPromise.catch(function() { 
  log('failed connecting to database:', e.message);
});

redisPromise.then(function() { 
  log('This shouldn't be called when connection fails :/');
});

答案 2 :(得分:1)

不是你想要的只是

new Promise(function(resolve, reject) {
  redisClient.on('error', reject);
  redisClient.on('ready', resolve);
}).then(function() {
  // THIS ISN'T CALLED - CORRECT
  log.enabled && log('connected, version: %s', redisClient.server_info.redis_version);
  return redisClient;
}).then(function() {
  log("This shouldn't be called when connection fails");
}).catch(function() {
  // THIS GETS CALLED - CORRECT
  log('failed connecting to database:', e.message);
});

与...相同:

try {
   var redisClient = ...
   log.enabled && log('connected, version: %s', redisClient.server_info.redis_version);
   log("This shouldn't be called when connection fails");
} 
catch(e) {
   log('failed connecting to database:', e.message);
}