我将如何构建一个复杂的 if / then 链与承诺?

How would I structure a complex if / then chain with promises?

具体来说,bluebird 兼容承诺

伪代码如下

if authentication
  db.findUser(authentication.userId).then (dbUser) ->
    sessionLogin dbUser
    # Done!
else
  if isSession req.user
    db.findUser(req.user.id).then (dbUser) ->
      db.addUserAuth(req.user.id, authentication).then (dbAuth) ->
        return
  else
    db.createUser(userDetails).then (dbUser) ->
      db.addUserAuth(dbUser.id, authentication).then (dbAuth) ->
        return

# Once all of that is done, do the following

if cookieSet
  db.findInvite(cookie.invitation).then (dbInvitation) ->
    if dbInvitation.Team
      db.createTeamMember(dbInvitation.Team, dbUser.id).then ->
        db.updateInvitation(marked: true).then ->
          done
    else
      done
else
  done

我不一定要寻找准确的代码、伪代码或想法就可以了。顺便说一下,这是用 CoffeeScript 编写的,尽管这无关紧要。

实际上看起来没什么不同,只是把承诺放在一起:

(if authentication
  db.findUser(authentication.userId).then (dbUser) ->
    sessionLogin dbUser
    .return dbUser
else
  (if isSession req.user
    db.findUser(req.user.id)
  else
    db.createUser(userDetails)
  ).then (dbUser) ->
    db.addUserAuth(dbUser.id, authentication)
    .return dbUser
).then (dbUser) ->
  if cookieSet
    db.findInvite(cookie.invitation).then (dbInvitation) ->
      if dbInvitation.Team
        db.createTeamMember(dbInvitation.Team, dbUser.id).then ->
          db.updateInvitation(marked: true)
.then ->
  done

好吧,promises 链,但它们不会像 if/else 那样神奇地抽象分支逻辑 - 你仍然会为此使用条件。虽然您的代码非常回调 - 您可以利用 promises 是值的代理这一事实并大大简化它:

if authentication
  user = db.findUser(authentication.userId)
  user_login = user.then (dbUser) -> sessionLogin dbUser 
  auth_user = user.return(user_login).return(user) # wait but keep value
else
  user = db.findUser(req.user.id) if isSession req.user else db.createUser(userDetails)
  auth_user = user.then(user->db.addUserAuth(req.user.id, authentication)).return(user)

auth_user.then (user) -> 
  if cookieSet
    db.findInvite(cookie.invitation)
.then (invite) ->
    if invite and invite.Team
      db.createTeamMember(dbInvitation.Team, dbUser.id)
.then val ->
   db.updateInvitation(marked: true) if val