无法catch到Promise中的reject?

新手上路,请多包涵

问题描述

用Koa写了个小程序的后端,在处理路由的training.js中调用了trainingController中的registerTraining()函数,整体流程是收到请求后,先判断请求参数中的用户位置信息,检测是否在要求的范围内,若不在,则返回错误信息给前端(主要问题所在),若符合要求,则操作数据库,报名成功。问题在于在training.js无法检测到registerTraining()的reject(),无法给前端返回正确的信息。

相关代码

training.js

const registerTraining = async ctx => {
  
  trainingController.registerTraining(ctx.params.trainingId, ctx.user.openId, {longitude: ctx.params.longitude, latitude: ctx.params.latitude}).then((result) => {
    ctx.body = {
      code: 0,
      msg: 'success'
    }
  }).catch((err) => {
    console.log(err)
    ctx.body = {
      code: 2,
      msg: 'fail'
    }
  })
}

trainingController.js

registerTraining = async (trainingId, openId, userLocation) => {
  return new Promise((resolve, reject) => {
    models.trainings.findOne({_id: trainingId}, (err, doc) => {
      if (err) {
        reject(err)
        // return
      }
      if (doc.register_location[0]) {
        let isNear = false
        for (latlng of doc.register_location) {
          let distance = distanceBetween(latlng, userLocation)
          console.log(`距离报名地点: ${distance}m`)
          if (distance < 150) {
            isNear = true
            break
          }
        }
        if (!isNear) {
          reject('需要在报名地点150米以内报名')
          // return
        }
      }
      if (doc.capacity > doc.participators.length) {
        models.users.update({openId: openId}, {$addToSet: {trainings: trainingId}}, (err) => {
          if (err) {
            reject(err)
          }
        });
        models.trainings.update({_id: trainingId}, {$addToSet: {participators: openId}}, (err, doc) => {
          if (err) {
            reject(err)
          }
          resolve(doc)
        })
      } else {
        models.trainings.update({_id: trainingId}, {$addToSet: {substitute_paticipators: openId}}, (err, doc) => {
          if (err) {
            reject(err)
          }
          resolve(doc)
        })
      }
    })
  })
}

你期待的结果是什么?实际看到的错误信息又是什么?

期待在reject(msg)时能够把msg返回给前端,但是现在无法收到reject()的内容。另外希望大佬们能够指点一下,如何让这个结构变得更合理更优雅。

阅读 2.9k
1 个回答

看了你的代码 问题就该出在这里:

if (doc.capacity > doc.participators.length) {
        models.users.update({openId: openId}, {$addToSet: {trainings: trainingId}}, (err) => {
          if (err) {
            reject(err)
          }
        });
        models.trainings.update({_id: trainingId}, {$addToSet: {participators: openId}}, (err, doc) => {
          if (err) {
            reject(err)
          }
          resolve(doc)
        })
      }
}

models.users.update,models.trainings.update 是两个并行的异步函数, 哪个先执行完, registerTraining 返回的状态就是哪一个
如果你的逻辑是 models.users.update 必须成功才执行 models.trainings.update 就不应该这么写.

至于你说的代码结构, 我稍微改了一下, 仅供参考:

registerTraining = async (trainingId, openId, userLocation) => {
    return new Promise((resolve, reject) => {
        models.trainings.findOne({ _id: trainingId }, (err, doc) => {
            if (err) return reject(err);
            resolve(doc);
        });
    })
    .then(doc => {
        if (doc.register_location[0]) {
            let isNear = false;
            for (latlng of doc.register_location) {
                let distance = distanceBetween(latlng, userLocation);
                console.log(`距离报名地点: ${distance}m`);
                if (distance < 150) {
                    isNear = true;
                    break;
                }
            }
            if (!isNear) {
                throw '需要在报名地点150米以内报名';
                // reject('需要在报名地点150米以内报名');
                // return
            }
        }
        return doc;
    })
    .then(doc => {
        if (doc.capacity > doc.participators.length) {
            return new Promise((resolve,reject)=>{
                models.users.update({ openId: openId }, { $addToSet: { trainings: trainingId } }, err => {
                    if (err) {
                        reject(err);
                    }
                    resolve();
                });
            }).then(()=>{
                return new Promise((resolve,reject)=>{
                    models.trainings.update(
                        { _id: trainingId },
                        { $addToSet: { participators: openId } },
                        (err, doc) => {
                            if (err) {
                                reject(err);
                            }
                            resolve(doc);
                        }
                    );
                })
            })
        } else {
            return new Promise((resolve,reject)=>{
                models.trainings.update(
                    { _id: trainingId },
                    { $addToSet: { substitute_paticipators: openId } },
                    (err, doc) => {
                        if (err) {
                            reject(err);
                        }
                        resolve(doc);
                    }
                );
            })
        }
    });
};

另外 如果把你的那些回调函数用 util.promisify 封装一下, 用起来会更舒服的 试试吧.

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题