0

我的函数中需要以下逻辑:

  1. 使用护照登录 facebook,我调用该方法来检索具有 facebook id 的用户。
  2. 如果用户存在,完成!
  3. 否则,我会调用该方法来使用电子邮件检索用户。
  4. 如果用户存在,我需要用 facebook id 更新用户并完成!
  5. 否则,如果用户不存在,我需要使用电子邮件和 facebook id 创建他的帐户。

例如,在 java 中,它会是这样的:

try {
  User user = userService.findByFacebookAccount(id);
  if(user != null) {
    done(user);
  } else {
    user = userService.findByEmail(email);
    if(user != null) {
      user.setFacebookAccount(id);
      if(userService.update(user)) {
        done(user); // Update with success
      } else {
        throws new Exception();
      }
    } else {
      user = userService.createByFacebookAccount(name, email, facebook_id);
      if(user != null) {
        done(user);
      } else {
        throws new Exception();
      }
    }
  }
} catch(Exception e) {
  done(e);
}

我如何组织它与 Promises 有关?我使用蓝鸟承诺如下:

function(accessToken, refreshToken, profile, done) {
  var profileInfos = profile._json;
  userService.findByFacebookAccount(profileInfos.id).then(function(user) {
    done(null, user);                                  
  }).error(function(e) {
    return userService.findByEmail(profileInfos.email);
  }).then(function(user) {            
    user.set('facebook_account', profileInfos.id);
    return userService.update(user, ['facebook_account']);
  }).then(function(user) {
    done(null, user);
  }).error(function(e) {        
    return userService.createByFacebookAccount(profileInfos.name, profileInfos.gender, profileInfos.username, profileInfos.email, profileInfos.id);
  }).then(function(user) {
    done(null, user);                    
  }).catch(function(e) {
    done(null);
  });
}

我认为这是错误的,因为当“return userService.update(user, ['facebook_account']);” 被拒绝我需要捕获错误并返回错误并且不创建用户。

从同步逻辑转换为承诺的最佳方法是什么?

4

1 回答 1

1

不要混合使用 Promise 和回调,除非你想创建一个回调 api 但想在内部使用 Promise(在这种情况下使用.nodeify)。也不要吞下错误并强迫用户检查返回值。

function doIt(accessToken, refreshToken, profile, done) {
  var profileInfos = profile._json;
  return userService.findByFacebookAccount(profileInfos.id).then(function(user) {
    if (user != null) {
      return user;
    }
    return userService.findByEmail(profileInfos.email).then(function(user) {
      if (user != null) {
        user.setFacebookAccount(id))
        return userService.update(user).then(function(updated) {
          // userService should actually just throw the error in the first place and not
          // swallow it and return false, which is making code much uglier than it needs to be here
          if (!updated) throw new Error();
          return user;
        });
      } else {
        return userService.createByFacebookAccount(name, email, facebook_id).then(function(user) {
          if (user != null) return user;
          throw new Error();
        })
      }
    })                                
  }).nodeify(done);
}

用法是:

doIt(...)
.then(function(user) {

})
.catch(function(error){

});

由于我们使用.nodeify()了 ,所以也支持回调接口:

doIt(..., function(err, user) {

});

如果服务使用异常而不是在发生错误时返回 null/false,它可能会稍微干净一些:

function doIt(accessToken, refreshToken, profile, done) {
  var profileInfos = profile._json;
  return userService.findByFacebookAccount(profileInfos.id).then(function(user) {
    if (user != null) {
      return user;
    }
    return userService.findByEmail(profileInfos.email).then(function(user) {
      if (user != null) {
        user.setFacebookAccount(id))
        return userService.update(user).thenReturn(user);
      } else {
        return userService.createByFacebookAccount(name, email, facebook_id)
      }
    })                                
  }).nodeify(done);
}
于 2014-05-04T18:34:58.450 回答