2016-11-08 90 views
0

我想嘗試將此函數轉換爲基於Promise的函數,以便解決所有這些嵌套回調和來自ESLint consistent-returnreturn警告。將嵌套的回調轉換爲Promise

以前,我在這裏要求一些幫助以克服ESLint錯誤,因爲它們不一致或遵循JS的最佳實踐。

我首先想到的是簡單地做return new Promise((resolve, reject) => {...})remove函數內部,但是這也只是promisify整個事情,而不是僅僅有什麼功能裏面,所以我覺得這不是要做到這一點的最好辦法。

任何幫助表示讚賞!

function remove(req, res) { 
    User.findOne({ username: req.params.username }, (findErr, existingUser) => { 
    if (findErr) return res.status(500).send(errorHandler.getErrorMessage(findErr)); 
    if (!existingUser) return res.status(404).send({ message: 'User not found' }); 

    existingUser.remove((removeErr) => { 
     if (removeErr) return res.status(500).send(errorHandler.getErrorMessage(removeErr)); 

     return res.json({ message: `${existingUser.username} successfully deleted` }); 
    }); 
    }); 
} 
+1

你在使用thsoe'findOne'和'remove'調用庫?它以某種方式支持承諾(可能通過簡單地省略回調)? – Bergi

+0

只需使用簡單的貓鼬進行數據庫查詢 – germainelol

回答

2

下面是另一種方法,你可以做到這一點。我通過將各個findOneremoveUser「promisifying」作爲單獨的功能開始。那麼,你的路線幾乎可以自動簡化。

你可以在這裏做一些改進,但也許你可以從中學到一些東西。

(感謝@Bergi了有益的建議)

const error = (type, message) => Object.assign(new Error(message), {type}); 
const wrapError = type => err => { throw error(type, errorHandler.getErrorMessage(err));}; 

const findUser = opts => { 
    return new Promise((resolve, reject) => { 
    User.findOne(opts, (err, user) => { 
     if (err) reject(err); 
     else resolve(user); 
    }); 
    }).then(user => { 
    if (!user) throw error('USER_NOT_FOUND', 'User not found') 
    else return user; 
    }, wrapError('USER_FIND_ERROR')); 
}; 

const removeUser = user => { 
    return new Promise((resolve, reject) => { 
    user.remove(err => { 
     if (err) reject(err); 
     else resolve(); 
    }); 
    }).catch(wrapError('USER_REMOVE_ERROR')); 
}; 

function remove(req, res) { 
    findUser({ username: req.params.username }) 
    .then(removeUser) 
    .then(() => res.json({message: `${req.params.username} successfully removed`})) 
    .catch(error) => { 
     switch (error.type) { 
     case 'USER_NOT_FOUND': 
      return res.status(404).send(error.message); 
     // case 'USER_FIND_ERROR': 
     // case 'USER_REMOVE_ERROR': 
     default: 
      console.error(error.type, error.message, error.stack); 
      return res.status(500).send(error.message); 
     } 
    }); 
} 
+0

我建議保持promisification簡單,只使用'if(err)reject(err)else resolve(...);'。如果您需要其他任何東西,比如'errorHandler.getErrorMessage'調用或空白測試,請在'then'或'catch'處理程序中執行。 – Bergi

+0

'const error =(type,message)=> Object.assign(new Error(message),{type});'? – Bergi

+0

@Bergi謝謝你的建議。你能詳細說明你提出的第一條評論嗎?如果這更簡單,請隨時編輯這個答案^ _^ – naomik

1

不知道是否有你的點,但你可能想嘗試以下

const findUser = (username) => { 
    return new Promise((resolve, reject) => { 
    User.findOne({ username }, (error, user) => { 
     if (error) { 
     reject({ type: 'error', details: errorHandler.getErrorMessage(error) }); 
     return; 
     } 

     if (!user) { 
     reject({ type: 'not-found', details: { message: 'User not found' } }); 
     return; 
     } 

     resolve(user); 
    }); 
    }); 
}; 

const removeUser = (username) => { 
    return new Promise((resolve, reject) => { 
    findUser(username) 
     .then(user => { 
     user.remove((error) => { 
      if (error) { 
      reject({ type: 'error', details: errorHandler.getErrorMessage(error) }); 
      return; 
      } 

      // Simply resolve on success 
      resolve(); 
     }); 
     }) 
     .catch(error => reject(error)); 
    }); 
}; 

function remove(req, res) { 
    removeUser(req.params.username) 
    .then(() => res.json({ message: `${req.params.username} successfully deleted` })) 
    .catch(error => { 
     if (error.type === 'not-found') { 
     return res.status(404).send(error.details); 
     } 

     return res.status(500).send(error.details); 
    }); 
} 

正如你可能已經注意到上述情況,一些行爲已經提取到返回承諾的功能。

可能有更多的優化,但我只是想向你展示Promise有什麼可能。

這有幫助嗎?

+0

有趣的是,使用Promise邏輯,它可以解決我的回調問題和我一致的返回問題。爲了讓我指出正確的方向,當你說這可以進一步優化時,你的意思是什麼?問我看起來很不錯。 – germainelol

+2

避免'removeUser'中的['Promise' constructor antipattern](http://stackoverflow.com/q/23803743/1048572)! – Bergi

+0

這裏有一個稍微優化版本:https://gist.github.com/maciejsmolinski/c176cb27c5a2d81104acd95ce10715ca –