2015-02-12 40 views
0

我正在構建這個承諾鏈。目標是讓第一個操作檢查數據庫中字段的唯一性,然後如果唯一,請保存該對象。但是如果對象不是唯一的,它不應該保存,並且應該返回錯誤響應。爲什麼我可以在鏈式鏈接中間得到一隻藍鳥捕捉其餘的鏈式執行

function(request, reply) { 
    var payload = request.payload; 

    checkThatEmailDoesNotExist().then(saveUser) 

    function checkThatEmailDoesNotExist() { 
    return User.where({email: payload.email}).countAsync() 
     .then(function(count) { 
     if (count > 0) { 
      throw Boom.badRequest('The email provided for this user already exists') 
     } 

     return null; 
     }) 
     .catch(function(err) { // ~This catch should stop the promise chain~ 
     reply(err); 
     }) 
    } 

    function saveUser() { 
    // ~But instead it is continuing on to this step~ 
    return User.massAssign(request.payload).saveAsync() 
     .spread(function(user, numAffected) { 
     return reply(user); 
     }) 
     .catch(function(err) { 
     server.log(['error', 'api', 'auth'], err); 
     throw Boom.badRequest('Object could not be saved to database'); 
     }); 
    } 
} 

如果錯誤在checkThatEmailDoesNotExist()拋出它的catch()應該返回錯誤,並停止處理當初的諾言鏈的其餘部分。

而不是這樣做,catch()觸發,然後繼續前進到saveUser()函數。

+1

捕獲收益「成功」並返回已解決(履行)的承諾。所以鏈接'然後'的**將被執行。爲了避免這種情況,請在'catch'函數內再次拋出錯誤。換句話說,你可以說拒絕只會沿着鏈條被捕獲一次(除非catch處理程序本身反覆拋出)。順便說一下,這是在某些人承諾應該使用的邊界上。通常,拒絕表示一些特殊情況。在這裏,您正在使用它們進行一些普通的舊重複檢查。 – 2015-02-12 12:35:47

回答

0

你在混合承諾和回調,這是一個可怕的反模式。來電者只需使用 返回的承諾,不需要手動將事情回傳給回叫。

function save(request) { 
    var payload = request.payload; 

    return User.where({email: payload.email}).countAsync() 
     .then(function(count) { 
     if (count > 0) { 
      throw Boom.badRequest('The email provided for this user already exists') 
     } 

     return User.massAssign(request.payload).saveAsync() 
     }) 
     .get(0) 
     /* equivalent to 
     .spread(function(user, numAffected) { 
     return user; 
     }) */ 
     .catch(Promise.OperationalError, function(err) { 
     server.log(['error', 'api', 'auth'], err); 
     throw Boom.badRequest('Object could not be saved to database'); 
     }); 
} 

用法:

save(request).then(function(user) { 
    response.render(...) 
}).catch(function(e) { 
    response.error(...) 
}) 

如果你想揭露回調API,理智的方式做到這一點是在現有承諾API結束對nodeify到螺栓和收工:

function save(request, callback) { 
    var payload = request.payload; 

    return User.where({email: payload.email}).countAsync() 
     .then(function(count) { 
     if (count > 0) { 
      throw Boom.badRequest('The email provided for this user already exists') 
     } 

     return User.massAssign(request.payload).saveAsync() 
     }) 
     .get(0) 
     /* equivalent to 
     .spread(function(user, numAffected) { 
     return user; 
     }) */ 
     .catch(Promise.OperationalError, function(err) { 
     server.log(['error', 'api', 'auth'], err); 
     throw Boom.badRequest('Object could not be saved to database'); 
     }) 
     .nodeify(callback); 
} 

save(request, function(err, user) { 
    if (err) return response.error(...); 
    response.render(...); 
}); 
相關問題