将嵌套回调转换为Promise

时间:2016-11-08 17:43:51

标签: javascript callback promise ecmascript-6 eslint

我想尝试将此函数转换为基于Promise的函数,以便从ESLint consistent-return解析所有这些嵌套回调和return警告。

之前,我在这里要求帮助克服ESLint错误和我的return语句,因为它们不一致或遵循JS的最佳实践。

我的第一个想法是简单地在return new Promise((resolve, reject) => {...})函数中执行remove,但这只会使整个事情变得无法实现,而不仅仅是函数内部的内容,所以我觉得这样做&#39 ;这不是最好的方法。

任何帮助表示赞赏!

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` });
    });
  });
}

2 个答案:

答案 0 :(得分:2)

这是你可以做到的另一种方式。我开始将每个findOneremoveUser“宣传”为单独的函数。然后,您的路线几乎会自动简化。

你可以在这里做一些改进,但也许你可以从中学到一些东西。

(感谢@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);
      }
    });
}

答案 1 :(得分: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的函数中。

可能已经进行了更多优化,但我只想向您展示Promise的可能性。

这有帮助吗?