如何拒绝(并正确使用)承诺? [英] How to reject (and properly use) Promises?

查看:60
本文介绍了如何拒绝(并正确使用)承诺?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

短篇小说:

  • 谈论 Promises/A + ,拒绝诺言的正确方法是什么-抛出错误?但是,如果我错过了catch-我的整个应用程序将会崩溃!

  • 如何使用promisify以及它的好处是什么(也许您需要阅读更长的版本)?

  • .then(success, fail)确实是反模式,我应该始终使用.then(success).catch(error)?

较长版本,描述为现实生活中的问题(希望有人阅读):

我有一个使用 Bluebird (A + Promise实现库)的库,用于从数据库中获取数据(谈论序列化).每个查询都返回一个结果,但有时为空(试图选择某些内容,但没有任何内容). Promise进入result函数,因为没有错误的理由(没有结果就不是错误).示例:

Entity.find(1).then(function(result) {
  // always ending here, despite result is {}
}).catch(function(error) {
  // never ends here
});

我想包装它并检查结果是否为空(无法在我的代码中到处检查).我是这样做的:

function findFirst() {
  return Entity.find(1).then(function(result) {
    if (result) { // add proper checks if needed
      return result; // will invoke the success function
    } else {
      // I WANT TO INVOKE THE ERROR, HOW?! :)
    }
  }).catch(function(error) {
    // never ends here
  });
}

findFirst().then(function(result) {
  // I HAVE a result
}).catch(function(error) {
  // ERROR function - there's either sql error OR there is no result!
});

如果您仍然与我在一起-我希望您能了解最新情况.我想以某种方式启动错误功能(其中错误功能"在其中).事情是-我不知道如何.我已经尝试过这些事情:

this.reject('reason'); // doesn't work, this is not a promise, Sequelize related
return new Error('reason'); // calls success function, with error argument
return false; // calls success function with false argument
throw new Error('reason'); // works, but if .catch is missing => BLOW!

正如您在我的评论(和每个规范)中所看到的,抛出错误的效果很好.但是,有一个很大的但是-如果我错过了.catch语句,我的整个应用程序都会崩溃.

为什么我不想要这个?假设我要在数据库中增加一个计数器.我不在乎结果-我只是发出HTTP请求.因此,我可以调用incrementInDB(),它具有返回结果的能力(即使出于测试原因),因此如果throw new Error失败了.但是由于我不在乎响应,有时我不会添加.catch语句,对吗?但是现在-如果我不这样做(故意或过失)-我最终会关闭您的节点应用程序.

我觉得不太好.有什么更好的方法来解决它,还是我只需要处理它?<​​/p>

我的一个朋友帮助了我,我使用了新的诺言来解决问题,如下所示:

function findFirst() {
  var deferred = new Promise.pending(); // doesnt' matter if it's Bluebird or Q, just defer
  Entity.find(1).then(function(result) {
    if (result) { // add proper checks if needed
      deferred.resolve(result);
    } else {
      deferred.reject('no result');
    }
  }).catch(function(error) {
    deferred.reject('mysql error');
  );

  return deferred.promise; // return a promise, no matter of framework
}

像魅力一样工作! 但是,我进入了这个页面:承诺反模式-Wiki文章由Bluebird(A +实现)的创建者Petka Antonov撰写.明确表示这是错误.

所以我的第二个问题是-是吗?如果是,为什么?最好的方法是什么?

非常感谢您阅读本文,我希望有人会花时间为我解答:)我应该补充一点,就是我不想过多地依赖框架,因此SequelizeBluebird只是事情而已最后我一起工作.我的问题是作为一个全球性的Promises,而不是这个特定的框架.

解决方案

每个帖子只问一个问题:-)

.then(success, fail)真的是反模式吗?我应该始终使用.then(success).catch(error)吗?

不. 它们只是做不同的事情,但是一旦您知道可以选择合适的东西.

如何使用promisify,它有什么好处?

我认为 Bluebird Promisification文档解释了这一点很好-它用于将回调API 转换为可返回承诺的API.

谈论Promises/A +,拒绝诺言的正确方法是-抛出错误?

是的,抛出错误是完全可以的. then回调中,您可以抛出该异常并将其自动捕获,从而导致结果承诺被拒绝.

您也可以使用return Promise.reject(new Error(…));;两者将具有完全相同的效果.

我的一个朋友帮助了我,我使用了新的诺言来解决问题,例如:[…]

不. 您真的不应该使用.只需使用then并在其中抛出或返回被拒绝的诺言即可.

但是,如果我错过了catch语句-我的整个应用程序将会崩溃!

不,不会.请注意,.catch()方法不是try catch语句-调用then回调的位置已经捕获了错误.然后,它仅作为参数传递给catch回调,不需要.catch()调用即可捕获异常.

当您错过.catch()时,您的应用程序将不会崩溃.发生的所有事情就是您有一个被拒绝的承诺,其余的应用程序将不受此影响.您将收到未处理的拒绝事件,该事件可以是anti-pattern and should I always use .then(success).catch(error)?

Longer version, described as real life problem (would love someone to read):

I have a library that uses Bluebird (A+ Promise implementation library), to fetch data from database (talking about Sequelize). Every query returns a result, but sometimes it's empty (tried to select something, but there wasn't any). The promise goes into the result function, because there is no reason for an error (not having results is not an error). Example:

Entity.find(1).then(function(result) {
  // always ending here, despite result is {}
}).catch(function(error) {
  // never ends here
});

I want to wrap this and check if the result is empty (can't check this everywhere in my code). I did this:

function findFirst() {
  return Entity.find(1).then(function(result) {
    if (result) { // add proper checks if needed
      return result; // will invoke the success function
    } else {
      // I WANT TO INVOKE THE ERROR, HOW?! :)
    }
  }).catch(function(error) {
    // never ends here
  });
}

findFirst().then(function(result) {
  // I HAVE a result
}).catch(function(error) {
  // ERROR function - there's either sql error OR there is no result!
});

If you are still with me - I hope you will understand what's up. I want somehow to fire up the error function (where "ERROR function" is). The thing is - I don't know how. I've tried these things:

this.reject('reason'); // doesn't work, this is not a promise, Sequelize related
return new Error('reason'); // calls success function, with error argument
return false; // calls success function with false argument
throw new Error('reason'); // works, but if .catch is missing => BLOW!

As you can see by my comments (and per spec), throwing an error works well. But, there's a big but - if I miss the .catch statement, my whole app blows up.

Why I don't want this? Let's say I want to increment a counter in my database. I don't care about the result - I just make HTTP request.. So I can call incrementInDB(), which has the ability to return results (even for test reasons), so there is throw new Error if it failed. But since I don't care for response, sometimes I won't add .catch statement, right? But now - if I don't (on purpose or by fault) - I end up with your node app down.

I don't find this very nice. Is there any better way to work it out, or I just have to deal with it?

A friend of mine helped me out and I used a new promise to fix things up, like this:

function findFirst() {
  var deferred = new Promise.pending(); // doesnt' matter if it's Bluebird or Q, just defer
  Entity.find(1).then(function(result) {
    if (result) { // add proper checks if needed
      deferred.resolve(result);
    } else {
      deferred.reject('no result');
    }
  }).catch(function(error) {
    deferred.reject('mysql error');
  );

  return deferred.promise; // return a promise, no matter of framework
}

Works like a charm! But I got into this: Promise Anti Patterns - wiki article written by Petka Antonov, creator of Bluebird (A+ implementation). It's explicitly said that this is wrong.

So my second question is - is it so? If yes - why? And what's the best way?

Thanks a lot for reading this, I hope someone will spent time to answer it for me :) I should add that I didn't want to depend too much on frameworks, so Sequelize and Bluebird are just things that I ended up working with. My problem is with Promises as a global, not with this particular frameworks.

解决方案

Please ask only a single question per post :-)

Is .then(success, fail) really an anti-pattern and should I always use .then(success).catch(error)?

No. They just do different things, but once you know that you can choose the appropriate one.

How to use promisify and what are the benefits of it?

I think the Bluebird Promisification docs explain this pretty well - it's used to convert a callback api to one that returns promises.

Talking about Promises/A+, what is the proper way to reject a promise - throwing an error?

Yes, throwing an error is totally fine. Inside a then callback, you can throw and it will be caught automatically, resulting to the rejection of the result promise.

You can also use return Promise.reject(new Error(…));; both will have absolutely the same effect.

A friend of mine helped me out and I used a new promise to fix things up, like this: […]

No. You really shouldn't use that. Just use then and throw or return a rejected promise in there.

But if I miss the catch statement - my whole app will blow!

No, it won't. Notice that .catch() method is not a try catch statement - the error will already be caught where your then callback was invoked. It is then only passed to the catch callback as an argument, the .catch() call is not required to capture exceptions.

And when you miss .catch(), your app won't blow. All what happens is that you have a rejected promise laying around, the rest of your app won't be affected by this. You will get an unhandled rejection event, which can be dealt with globally.

Of course, that should not happen; every promise chain (not every promise instance) should be ended with a .catch() that handles errors appropriately. But you definitely don't need .catch() in every helper function, when it returns a promise to somewhere else then errors will usually be handled by the caller.

这篇关于如何拒绝(并正确使用)承诺?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆