理解显式承诺构造反模式 [英] Understanding explicit promise construction anti pattern

查看:23
本文介绍了理解显式承诺构造反模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

CertainPerformance 在我的 上一篇 建议我参考 stackoverflow 中的以下问题

CertainPerformance highlighted in my previous post advised me to avoid the explicit Promise construction antipattern with reference to to following question in stackoverflow

坦率地说,我是 JS 和 node 的新手,我并没有经常使用 promise.我去阅读了那些文章,但要么我无法理解或无法联系,要么我对 Promise 的理解在某个地方一直模糊/错误

Frankly, Speaking, I am new to JS and node and I haven't used promise a lot. I went and read those article but either I was unable to comprehend or unable to relate or maybe somewhere my understanding of promises have been vague/wrong all together

所以我决定在一个新线程中提出这个问题并寻求帮助.

So I decided to ask this question in a new thread and seek for help.

我正在创建帮助程序/通用函数,我可以用它来保持我的代码整洁,如果我想随时更改函数内部的任何内容,我不必手动更改每个函数.

I am creating helper/common function which I could use to keep my code tidy and if in case I want to change anything inside function at anytime, I don't have to manually change every function.

这些就是我做的功能

//Find user by email Address 
const findUserByEmail = (emailAddress) => {
    return new Promise((resolve, reject) => {
     User.findOne({email: emailAddress}).then(response => {
        resolve(res)
      }).catch(error => {
        reject("Error in findUserByEmail", error);
      })
    })
}

//Create User 
const createNewUser = (newUserDetails) => {
    return new Promise((resolve, reject) => {
      new User({
         fullName: newUserDetails.fullName,
         email: newUserDetails.email,
         image: newUserDetails.image,
         gender: newUserDetails.gender,
         age: newUserDetails.age
      }).save().then((response) => {
          resolve(response)
      }).catch((error) => {
          reject("Problem in Creating New User", error)
      })
    })
}

问题 1

现在,我假设CertainPerformance说过度使用了promise,因为我正在创建新的promise return new Promise((resolve, reject) => { 当我已经在使用 mongoose 的promise <代码>User.findOne({email: emailAddress}).then(response => { ?

Question 1

Now, I am assuming CertainPerformance said the excessive use of promises because I am creating new promise return new Promise((resolve, reject) => { when I am already using promises with mongoose User.findOne({email: emailAddress}).then(response => { ?

但我创建这些承诺的原因是,当我在导入后从我的应用程序的任何地方调用这些辅助函数时

But the reason for me to create those promise was, when I call these helper function from anywhere in my app after importing

const { findUserByEmail } = require("./my_db_query");

我可能希望它返回响应或在出错时抛出错误

I would probably want it return a response or throw an error in case of error

findUserByEmail("test@example.com").then(/*...*/).catch(/*...*/);

如果我改变了上面的代码片段而不添加新的承诺

If I change my above code snippet without adding new promise

 function findUserByEmail  (email) {
       return User.findOne({email: email}).then(currentUser => currentUser).catch(error => error)
    } 

问题 2

然后我可能无法在 findUserByEmail("test@example.com").then.catch强>?

Question 2

Then I won't probably be able to .then and .catch in findUserByEmail("test@example.com")?

在应用程序的 API 路由中,我将在其中调用 findUserByEmail("test@example.com") 函数,如果出现错误(这会不同的情况会有所不同,因此我不能在我的辅助函数中使用它).

And In API route of App, where I would be calling the findUserByEmail("test@example.com") function, I would want to do something else if there is an error (which would be different for different case and hence I cannot use it in my helper function).

确实,现在做 return new Promise((resolve, reject) => { 而不是只做一个 return User.findOne( 或 am我错过了什么?

Does, it make sense now for doing return new Promise((resolve, reject) => { instead of doing just one return User.findOne( or am I missing something?

推荐答案

因为 .findOne 已经返回了一个 Promise,所以不需要用 new Promise - 相反,只需使用 .then.catch 将现有的 Promise链接到> 根据需要.这样的 Promise 链可以有 任意数量.thens 和 .catchs - 仅仅因为你使用了 Promise 和一个 .then 不会阻止您在其他地方使用相同的解析值.举例说明:

Because .findOne already returns a Promise, there's no need to construct a new one with new Promise - instead, just chain onto the existing Promise chain with .then and .catch as needed. Such Promise chains can have any number of .thens and .catchs - just because you consume a Promise with one .then doesn't prevent you from using the same resolve value elsewhere. To illustrate:

makePromise()
  .then((result) => {
    console.log(result);
    // Returning inside a `.then` will pass along the value to the next `.then`:
    return result;
  })
  .then((result) => {
    // this `result` will be the same as the one above
  });

换句话说 - 没有必要在每次您希望能够使用另一个 .then 时构建一个 new Promise.所以:

In other words - there's no need to construct a new Promise every time you want to be able to use another .then. So:

那么我可能无法在 findUserByEmail("test@example.com") 中使用 .then 和 .catch

Then I won't probably be able to .then and .catch in findUserByEmail("test@example.com")

不正确 - 您确实可以根据需要使用任意数量的 .then.catch 链接到现有 Promise 的末尾.

isn't correct - you can indeed chain onto the end of an existing Promise with as many .thens and .catches as you want.

请注意,一个 .then 只返回其参数而不执行其他任何操作(例如 .then(currentUser => currentUser))是多余的 - 它不会什么都不做.另请注意,.catch 将捕获 Promise 拒绝 并解析为 resolved Promise.所以如果你这样做

Note that a .then which only returns its parameter and does nothing else (such as .then(currentUser => currentUser)) is superfluous - it won't do anything at all. Also note that a .catch will catch Promise rejections and resolve to a resolved Promise. So if you do

function findUserByEmail(email) {
  return User.findOne({email: email})
    .then(currentUser => currentUser)
    .catch(error => error)
}

那个catch 意味着findUserByEmail 的调用者将不能catch 错误,因为任何可能的错误被findUserByEmailcatch 捕获.通常,允许错误渗透到函数的调用者是一个好主意,这样你就可以,例如:

that catch means that callers of findUserByEmail will not be able to catch errors, because any possible errors were caught in findUserByEmail's catch. Usually, it's a good idea to allow errors to percolate up to the caller of the function, that way you could, for example:

someFunctionThatReturnsPromise('foobar')
  .then((result) => {
    // everything is normal, send the result
    res.send(result);
  })
  .catch((err) => {
    // there was an error, set response status code to 500:
    res.status(500).send('there was an error');
  })

因此,除非您的 findUserByEmailcreateNewUser 辅助函数需要在出现错误时执行特定操作,否则最好只是单独返回 Promise:

So, unless your findUserByEmail or createNewUser helper functions need to do something specific when there's an error, it would probably be best just to return the Promise alone:

const findUserByEmail = email => User.findOne(email);
const createNewUser = newUserDetails => new User(newUserDetails).save();

如果您的辅助函数 do 需要在出现错误时执行某些操作,那么为了确保错误正确传递给函数的调用者,我建议您要么抛出错误catch 里面:

If your helper functions do need to do something when there's an error, then to make sure that the error gets passed along properly to the caller of the function, I'd recommend either throwing the error inside the catch:

const findUserByEmail = email => User.findOne(email)
  .catch((err) => {
    // error handling - save error text somewhere, do a console.log, etc
    throw err;
  });

这样你就可以在其他东西调用 findUserByEmailcatch.否则,如果你做类似的事情

so that you can catch when something else calls findUserByEmail. Otherwise, if you do something like

const findUserByEmail = email => User.findOne(email)
  .catch((err) => {
    // do something with err
    return err;
  });

然后 findUserByEmail 的调用者将不得不检查 .then 中的结果是否确实是一个错误,这很奇怪:

then the caller of findUserByEmail will have to check inside the .then if the result is actually an error, which is weird:

findUserByEmail('foo@bar.com')
  .then((result) => {
    if (result instanceof Error) {
      // do something
    } else {
      // No errors
    }
  });

最好在findUserByEmailcatch中抛出错误,这样findUserByEmail的consumer可以.catch.

Better to throw the error in findUserByEmail's catch, so that the consumer of findUserByEmail can also .catch.

这篇关于理解显式承诺构造反模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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