Javascript中不同的承诺途径

时间:2018-04-24 04:07:38

标签: javascript promise es6-promise

我正在试图找到一种编程函数的方法,这样它就能够处理不同的promise链路而不会重复代码。

通过一个具体的例子,我将详细阐述这个问题。

我有一个简单的API来更新用户的个人资料。它需要作为参数,新电子邮件或新用户名,或两者兼而有之。如果提供了用户名,我想验证是否未使用名为getExistingUser(username)的函数来返回一个解析为实际用户数据的promise。因此,代码片段就像

if (body.newUserName) {
  getExistingUser(newUserName).then((existingUser) => {
    if (existingUser) // return bad request error
    else sql.update(newInfo) // an object that contains username (and email)
  })
} else {
  sql.update(newInfo) // an object that contains new email only
}

现在的挑战是,如果提供了用户名,则对用户配置文件的更新必须进入getExistingUser().then()。但是,如果仅提供电子邮件,则完全相同的代码blob更新sql 将必须追踪getExistingUser,从而导致代码重复。是否有一种构建器方法可以让我决定将哪些承诺链接起来,以便可以避免这种代码重复?

3 个答案:

答案 0 :(得分:1)

对于像这样的情况,我个人更喜欢创建一个promisified验证函数,以保持我的承诺链完整,防止代码重复,例如

function saveUser(params) {
  return validateRequest(params)
    .then(function(validatedParams) {
      db.updateUser(validatedParams)
    })
}

function validateRequest(params) {
  if(!params.email && !params.username) return {}
  var parsedParams = {}
  var promises = []

  if(params.email) {
    parsedParams.email = params.email
    promises.push(getUserByEmail(parsedParams.email))
  }
  if(params.username) {
    parsedParams.username = params.username
    promises.push(getUserByUsername(parsedParams.username))   
  }

  return Promise.all(promises).then(function(results) {
    if(results.length > 0) {
      throw new Error("Username or email already exists")
    } else {
      return parsedParams
    }
  })

}

答案 1 :(得分:0)

你似乎在寻找

(body.newUserName
  ? getExistingUser(newUserName).then(existingUser => {
      if (existingUser) throw new Error("400 Bad request");
      // else return undefined
    })
  : Promise.resolve(/* undefined */)
).then(() => {
  return sql.update(newInfo)
}, err => {
  // do something with the bad request errors
})

使用async / await

更加轻松
if (body.newUserName) {
  const existingUser = await getExistingUser(newUserName);
  if (existingUser) {
    throw …; // or return
  }
}
await sql.update(newInfo);

答案 2 :(得分:-1)

您可以尝试将所有内容限定在匿名函数中,并将本地函数作为回调添加。

(function() {
    getExistingUser(body.newUserName)
        .then(processUser, showErrorMessage);

    function processUser(user) {
    }

    function showErrorMessage() {
    }
})();

当您的代码变得更复杂并且在调试时需要更多有用的堆栈跟踪时,这也很有用。

- 更新

我刚刚重新阅读了您的帖子,虽然我的解决方案并非完全符合您的要求,但根据您的目的修改它是微不足道的。这也使人们非常清楚预期会发生什么。如果找到用户,请做一件事,否则做其他事情。如果你需要在两个实例中做同样的事情,那么最明确的事情就是创建另一个函数并从两个方法中调用它。这不是重复代码。