2016-09-28 58 views
0

首先,我不會否認我對承諾非常陌生,並試圖更好地管理我的新Node.js應用程序中的承諾。基於我從朋友和社區那裏聽到的信息,我正在使用藍鳥。這裏有一個場景:在藍鳥的順序流程中管理異步操作

的應用程序有一個註冊流程,一個典型的使用情況在以下事件,以註冊新用戶發生:

  1. 如果用戶已經存在檢查。
  2. 如果不是,請添加新用戶。
  3. 發送驗證電子郵件。

我確實有3個獨立的函數來解決上述每個步驟。

現在,這裏是我想出了利用諾言流...但不知何故,我不相信下面的代碼:

user.isExistingUser(email) 
     .then((successData) => { 
      if(successData && successData.length === 0) { 
       user.signUp(signUpInfo) 
       .then((successData) => { 
        emailService.sendVerificationEmail(recipientInfo) 
        .then((successData) => { 
        res.json(responseUtility.getApiResponse(successData)); 
        }) 
        .catch((errorObj) => { 
         res.json(responseUtility.getApiResponse(null, null, errorObj)); 
        }); 
       }) 
       .catch((errorObj) => { 
        res.json(responseUtility.getApiResponse(null, null, errorObj)); 
       }); 
      } else { 
       res.json(responseUtility.getApiResponse(null, [{ 
        param: 'email', 
        msg: 'An account already exists with this email' 
       }], null)); 
      } 
     }) 
     .catch((errorObj) => { 
      res.json(responseUtility.getApiResponse(null, null, errorObj)); 
     }); 

正如你可以看到代碼似乎有點太長了,可以成爲跟蹤有點棘手。這裏的一些藍鳥專家可以幫助提供更好或更易讀的代碼嗎?

+0

確實[這](https://jsfiddle.net/18dbrwxv/1/)幫助 –

+0

@JaromandaX感謝快速反應......我不知道會發生什麼,如果電子郵件驗證步驟失敗......在任何錯誤可以在最後捕獲.catch塊嗎?我也想知道如果我可以在藍鳥中使用.mapseries api嗎? – NiK

+1

是的,單catchblock將捕獲任何拒絕 - 我不知道藍鳥承諾糖,我獨家使用本機承諾 - 儘管藍鳥驚人的明顯的性能優勢 - 不知道爲什麼你會在這種情況下使用它 –

回答

2

你應該更好地利用鏈接。始終return承諾您的功能,做一些異步的。

user.isExistingUser(email).then(successData => { 
    if (successData && successData.length === 0) { 
     return user.signUp(signUpInfo).then(() => { 
//  ^^^^^^ 
      return emailService.sendVerificationEmail(recipientInfo); 
//   ^^^^^^ 
     }).then(successData => { 
      res.json(responseUtility.getApiResponse(successData)); 
     }); 
    } else { 
     res.json(responseUtility.getApiResponse(null, [{ 
      param: 'email', 
      msg: 'An account already exists with this email' 
     }], null)); 
    } 
}).catch(errorObj => { 
    res.json(responseUtility.getApiResponse(null, null, errorObj)); 
}); 
0

我想一個合理的方式來實現相同的代碼可能是這樣的;

user.isExistingUser(email) 
    .then(successData => successData && 
         successData.length === 0 ? user.signUp(signUpInfo) 
                 .then(successData => emailService.sendVerificationEmail(recipientInfo)) 
                 .then(successData => res.json(responseUtility.getApiResponse(successData))) 
                : res.json(responseUtility.getApiResponse(null, [{param: 'email', msg: 'An account already exists with this email'}], null))) 
    .catch(err => res.json(responseUtility.getApiResponse(null, null, err))); 
1

Unserstand什麼是你的代碼錯誤

基本上,你的代碼是嵌套的回調。典型的嵌套回調是這樣的:

funcation(args.., 
    function(args..., 
     function(args){...} 
    ){...} 
){...} 

此致是這樣:

function(args).then(()=> { 
    function(args).then(() => { 
     function(args){...} 
    }) 
}) 

沒有太大的區別,是不是?


這是使用Promise的正確方法。

解決您的問題的關鍵是鏈接的承諾。這實際上是整個承諾的重點。

基本上,你想讓你的then回調返回一個承諾。這樣你可以鏈接你的承諾,以避免嵌套的回調風格的代碼。

每個.then方法總是返回一個承諾本身。

promiseB = promiseA.then(()=> { 
    // callback 
    return promiseC 
}); 

如果callback回報像上面一個承諾,effectily你能想到的promiseB = promiseC。現在,如果我們有

promiseC = promiseA.then(()=> { 
    // callback 
    return promiseB 
}); 
promiseE = promiseC.then(()=> { 
    // callback 
    return promiseD 
}); 

您可以在一起。然後上面可以縮短爲:

promiseA.then(()=> { 
    // callback 
    return promiseB 
}).then(()=> { 
    // callback 
    return promiseD 
}); 

回答您直接質疑。

let userPromise = user.isExistingUser(email); 
 

 
// handle new user 
 
userPromise 
 
.then((userData) => { 
 
    assert userData.length === 0; 
 
    // sign up 
 
    // Assuming user.signUp is a Promise with recipientInfo as its resolved value 
 
    return user.signUp(userData.signUpInfo); 
 
}) 
 
.then((recipientInfo)=> { 
 
    // send verification email 
 
    // Assuming user.sentVerificationEmail is a Promise with emailSuccessData as its resolved value 
 
    return user.sentVerificationEmail(recipientInfo) 
 
}) 
 
.then((emailSuccessData)=> { 
 
    res.json(responseUtility.getApiResponse(emailSuccessData)); 
 
}) 
 
// if any of the previous Promise is rejected, 
 
// the follow .then will be effectively bypassed and fall though to this catch 
 
.catch((err)=> { 
 
    res.json(responseUtility.getApiResponse(null, null, err)); 
 
}) 
 

 

 
// handle existing user 
 
userPromise.then((successData) => { 
 
    assert successData.length > 0 
 
    const json = [{ 
 
    param: 'email', 
 
    msg: 'An account already exists with this email' 
 
    }] 
 
    res.json(responseUtility.getApiResponse(null, json, null)); 
 
}); 
 
// no need to catch again. if userPromise is rejected, it will be handled by the catch above.