1

好吧,我以为我已经理解了 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进行全面讨论

4

3 回答 3

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);
}
于 2014-03-19T20:52:18.063 回答
1

then在一些库中创造了一个新的承诺。我的猜测是 bluebird 也会用catch. 您链接它们的方式redisPromise是指“捕获”承诺,而不是第一个承诺。而“赶上”确实解决了。

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

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");
});
于 2014-03-19T19:10:34.857 回答
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 :/');
});
于 2014-03-19T20:23:43.250 回答