Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/425.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 理解明确承诺结构反模式_Javascript_Node.js_Mongoose_Promise - Fatal编程技术网

Javascript 理解明确承诺结构反模式

Javascript 理解明确承诺结构反模式,javascript,node.js,mongoose,promise,Javascript,Node.js,Mongoose,Promise,在我的文章中强调,建议我避免引用到的显式承诺构造反模式 坦白地说,我对JS和node还不熟悉,也没有太多使用promise。我去看了那篇文章,但要么我无法理解,要么我无法叙述,要么我对承诺的理解一直模糊/错误 所以我决定用新的思路问这个问题并寻求帮助 那么我在做什么,为什么要这么做 我正在创建helper/common函数,我可以使用它来保持代码整洁,如果我想随时更改函数中的任何内容,我不必手动更改每个函数 这些就是我做的函数 //Find user by email Address cons

在我的文章中强调,建议我避免引用到的显式承诺构造反模式

坦白地说,我对JS和node还不熟悉,也没有太多使用promise。我去看了那篇文章,但要么我无法理解,要么我无法叙述,要么我对承诺的理解一直模糊/错误

所以我决定用新的思路问这个问题并寻求帮助

那么我在做什么,为什么要这么做 我正在创建helper/common函数,我可以使用它来保持代码整洁,如果我想随时更改函数中的任何内容,我不必手动更改每个函数

这些就是我做的函数

//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说过度使用承诺是因为我正在创建新的承诺返回新的PromiseSolve,reject=>{当我已经对mongoose用户使用承诺时。findOne{email:emailAddress}。然后Response=>{

但我之所以做出这些承诺,是因为我在导入后从应用程序的任何地方调用这些帮助函数

const { findUserByEmail } = require("./my_db_query");
我可能希望它返回一个响应,或者在出现错误时抛出一个错误

findUserByEmail("test@example.com").then(/*...*/).catch(/*...*/);
如果我在不添加新承诺的情况下更改上述代码段

 function findUserByEmail  (email) {
       return User.findOne({email: email}).then(currentUser => currentUser).catch(error => error)
    } 
问题2 那我就不可能了。然后,然后,然后,赶上findUserByEmailtest@example.com?

在应用程序的API路径中,我将调用findUserByEmailtest@example.com函数,如果出现错误,则我希望执行其他操作,该错误对于不同的情况会有所不同,因此我无法在助手函数中使用它

问题3
现在执行return new Promiseresolve,reject=>{而不是只执行一个return User.findOne或者我遗漏了什么吗?

当存在承诺时,使用承诺构造函数创建承诺是没有意义的,这就是为什么它被称为承诺构造反模式

这是一个错误,FindUserByMail中的rejectError,error。reject只接受1 参数,这是拒绝原因。错误将被忽略。错误通常是错误对象而不是字符串

该函数可以重构为:

   const findUserByEmail = (emailAddress) => {
     return User.findOne({email: emailAddress})
     .then(response => response) // noop
     .catch(error => {
        const readableError = new Error('Error in findUserByEmail');
        readableError.originalError = error;
        throw readableError;
      });
    })
  }
等等

反模式不一定会导致糟糕的性能,但它们会导致代码气味。它们使代码更难阅读、维护和测试,还表明开发人员可能对该主题理解不足

承诺构造函数对性能的影响很小。它引入了另一个嵌套级别,并有助于回调地狱-承诺应该有助于避免它

如果我在不添加新承诺的情况下更改上述代码段 那我就不可能了。然后,然后,然后,赶上findUserByEmailtest@example.com?


不,承诺可以与then…和catch…链接,这是thennull的语法糖,…根据需要多次链接,这是该模式的优点。请注意catcherr=>{return err}和catcherr=>{throw err}不是同一件事,前者捕获错误,后者将其重新引用。

当存在承诺时,使用承诺构造函数创建承诺是没有意义的,这就是为什么称之为承诺构造反模式

这是一个错误,FindUserByMail中的rejectError,error。reject只接受1 参数,这是拒绝原因。错误将被忽略。错误通常是错误对象而不是字符串

该函数可以重构为:

   const findUserByEmail = (emailAddress) => {
     return User.findOne({email: emailAddress})
     .then(response => response) // noop
     .catch(error => {
        const readableError = new Error('Error in findUserByEmail');
        readableError.originalError = error;
        throw readableError;
      });
    })
  }
等等

反模式不一定会导致糟糕的性能,但它们会导致代码气味。它们使代码更难阅读、维护和测试,还表明开发人员可能对该主题理解不足

承诺构造函数对性能的影响很小。它引入了另一个嵌套级别,并有助于回调地狱-承诺应该有助于避免它

如果我在不添加新承诺的情况下更改上述代码段 那我就不可能了。然后,然后,然后,赶上findUserByEmailtest@example.com?

不,承诺可以与then…和catch…链接,这是thennull的语法糖,…根据需要多次链接,这是该模式的优点。请注意catcherr=>{return err}和catcherr=>{throw err}不同的是,前者捕获一个错误,后者将其重新引用。

因为.findOne已经返回了一个承诺,没有必要用新的承诺构造一个新的承诺-相反,只需根据需要用.then和.catch链接到现有的承诺链上。这样的承诺链可以有任意数量的.thens和.catch-因为你用承诺来消费承诺。这并不妨碍你在其他地方使用相同的解析值。举例说明:

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
  });
换句话说,没有必要在每次你想使用另一个承诺的时候都构建一个新的承诺 . 因此:

那我就不可能了。然后,然后,然后,赶上findUserByEmailtest@example.com

不正确-您确实可以使用任意数量的.thens和.catch将现有承诺的末尾链接到

请注意,.then只返回其参数,而不执行其他操作,如.thencurrentUser=>currentUser,这是多余的-它根本不会执行任何操作。还要注意.catch将捕获拒绝的承诺并解析为已解析的承诺。所以如果你这样做了

function findUserByEmail(email) {
  return User.findOne({email: email})
    .then(currentUser => currentUser)
    .catch(error => error)
}
该捕获意味着FindUserByMail的调用方将无法捕获错误,因为任何可能的错误都是在FindUserByMail的捕获中捕获的。通常,允许错误渗透到函数的调用方是一个好主意,您可以这样做,例如:

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');
  })
因此,除非FindUserByMail或createNewUser助手函数在出现错误时需要执行某些特定操作,否则最好仅返回承诺:

如果您的助手函数确实需要在出现错误时执行某些操作,那么为了确保将错误正确地传递给函数的调用方,我建议您在catch中抛出错误:

这样你就可以在其他东西调用FindUserByMail时捕获。否则,如果你这样做

const findUserByEmail = email => User.findOne(email)
  .catch((err) => {
    // do something with err
    return err;
  });
然后FindUserByMail的调用者必须检查内部。然后,如果结果实际上是一个错误,这很奇怪:

findUserByEmail('foo@bar.com')
  .then((result) => {
    if (result instanceof Error) {
      // do something
    } else {
      // No errors
    }
  });
最好在FindUserByMail的catch中抛出错误,这样FindUserByMail的使用者也可以.catch.

因为.findOne已经返回了一个承诺,没有必要用新的承诺构造一个新的承诺-相反,只要根据需要用.then和.catch链接到现有的承诺链上即可。这样的承诺链可以有任意数量的.thens和.catch,这仅仅是因为您使用了一个承诺,但这并不妨碍您在其他地方使用相同的解析值。举例说明:

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
  });
换句话说,没有必要在每次你想使用另一个承诺的时候都构建一个新的承诺。因此:

那我就不可能了。然后,然后,然后,赶上findUserByEmailtest@example.com

不正确-您确实可以使用任意数量的.thens和.catch将现有承诺的末尾链接到

请注意,.then只返回其参数,而不执行其他操作,如.thencurrentUser=>currentUser,这是多余的-它根本不会执行任何操作。还要注意.catch将捕获拒绝的承诺并解析为已解析的承诺。所以如果你这样做了

function findUserByEmail(email) {
  return User.findOne({email: email})
    .then(currentUser => currentUser)
    .catch(error => error)
}
该捕获意味着FindUserByMail的调用方将无法捕获错误,因为任何可能的错误都是在FindUserByMail的捕获中捕获的。通常,允许错误渗透到函数的调用方是一个好主意,您可以这样做,例如:

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');
  })
因此,除非FindUserByMail或createNewUser助手函数在出现错误时需要执行某些特定操作,否则最好仅返回承诺:

如果您的助手函数确实需要在出现错误时执行某些操作,那么为了确保将错误正确地传递给函数的调用方,我建议您在catch中抛出错误:

这样你就可以在其他东西调用FindUserByMail时捕获。否则,如果你这样做

const findUserByEmail = email => User.findOne(email)
  .catch((err) => {
    // do something with err
    return err;
  });
然后FindUserByMail的调用者必须检查内部。然后,如果结果实际上是一个错误,这很奇怪:

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

最好在FindUserByMail的catch中抛出错误,这样FindUserByMail的使用者也可以.catch.

如果有任何错误,您可以抛出它,并且可以在调用方函数findUserByMail email{return User.findOne{email:email}中捕获它。然后currentUser=>currentUser.catch函数err{//throw要由端点处理的错误throw err;}}如果有任何错误,您可以抛出它,并且可以在调用方函数findUserByEmail email{return User.findOne{email:email}中捕获它。thencurrentUser=>currentUser.catchfunction err{//throw要由端点throw err处理的错误;}现在这很有意义。你能回答问题的第二部分吗?我已经添加了一些解释。我相信它已经回答了问题1-3。还有什么需要解决的吗?当调用FindUserByMail函数,即findUserByEmailtest@example.com,我能做什么findUserByEmailtest@example.com.thenresponse=>response.catcherr或者=>如果我没有返回新PromiserSolve,则返回错误=>{我更新了答案。是的,你可以,这就是为什么新承诺是多余的重点和实际原因。请注意。catcherror=>error捕获错误,而在new Promise中,你拒绝它。如果你想重新获得它,应该有抛出错误。很高兴它有帮助。这现在很有意义。你能回答问题的第二部分吗我加了一些解释,我相信
已经回答了问题1-3。调用FindUserByMail函数(即findUserByEmailtest@example.com,我能做什么findUserByEmailtest@example.com.thenresponse=>response.catcherror=>error如果我没有返回新的Promisersolve,拒绝=>{我更新了答案。是的,你可以,这就是为什么新承诺是多余的重点和实际原因。请注意。catcherror=>error捕获错误,而在新承诺中,你拒绝它。如果你想重新获得它,应该有抛出错误。很高兴它有帮助。我真的比你发誓,@estus向我解释了承诺是如何像任何人一样工作的她曾经做过。非常感谢你的回答:我真的比你发誓,@estus向我解释了承诺是如何像其他人一样工作的。非常感谢你的回答: