Unable to catch to reject? in Promise

problem description

Mini Program"s backend is written in Koa, and the registerTraining () function in trainingController is called in the training.js for routing. The whole process is to determine the user location information in the request parameters after receiving the request, and check whether it is within the required range. If not, an error message is returned to the frontend (where the main problem lies). If the request is met, the database is operated and the registration is successful. The problem is that the reject (), of registerTraining () cannot be detected in training.js and cannot return the correct information to the front end.

related codes

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

what result do you expect? What is the error message actually seen?

expects to be able to return msg to the front end on reject (msg), but cannot receive the contents of reject () at this time. In addition, I hope the bosses can give us some advice on how to make this structure more reasonable and elegant.


after reading your code, the problem should be here:

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 are two parallel asynchronous functions. Which one finishes first, registerTraining returns the state
if your logic is models.users.update , you should not write this way if you must execute models.trainings.update successfully.

as for the code structure you mentioned, I changed it a little bit for reference only:

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

in addition, if you encapsulate your callback functions with util.promisify , it will be more comfortable to try.

Menu