2016-11-08 109 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 –