通过.catch()传播被拒绝的承诺

时间:2017-05-16 17:57:30

标签: javascript node.js typescript promise

我有一些基本上看起来像这样的代码:

export function firstFunction(req: express.Request, res: express.Response, next: express.NextFunction): void {
  secondFunction(id)
  .then((userId: UserId) => {
    res.status(200).send(UserId);
  })
  .catch((err) => {
    if (err instanceof NoResultError) {
      res.status(404).send(err);
    } else {
      next(err);
    }
  });
}


export function secondFunction(id: string): Promise<UserId> {
  return new Promise<UserId>((resolve, reject) => {
    thirdFunction(id)
    .then((data: TableInfo) => {
      if (Object.keys(data).length !== 3) {
        reject(new Error('data in database is not mapped properly'));
      }
      resolve(data);
    })
    .catch((err) => {
      // WANT TO PROPAGATE ERROR UP TO THE GETDETAILS FUNCTION WHICH CALLS THIS
    });
  });
}

export function thirdFunction(id: string): Promise<TableInfo> {
  return new Promise<TableInfo>((resolve, reject) => {
    let query = `
        //query goes here
    `;
    db.executeQuery(query, [id])
    .then((data: TableInfo) => {
      if (Object.keys(data).length < 1) {
        reject(new NoResultError('some message here'));
      }
      resolve(data);
    });
  });
}

我的目标是让三个函数中的最低级别(thirdFunction)确定来自db-query的数据是否找不到数据,然后拒绝该带有错误的promise。然后第二个函数应理想地捕获此错误并将其传播到firstFunction,以便firstFunction可以正确处理该错误。我尝试过throw err一个return err和一个return Promise.reject(err)所有这些导致未经处理的承诺拒绝。什么是我(可能是根本的)对这应该如何运作的误解?

1 个答案:

答案 0 :(得分:3)

  理想情况下,secondFunction应该捕获此错误并将其传播

不,传播是默认值。理想情况下,您根本不需要捕获它,它会自动传播。

  

我尝试了所有导致未经处理的承诺拒绝的事情。我的(可能是根本的)误解是什么?

您正在使用Promise constructor antipattern!有了它,您需要在reject(err)处理程序中调用catch才能使其正常工作。或者真的.then(resolve, reject);。但这绝对不是应该如何做到的。

相反,删除new Promise包装器,只返回链接then处理程序的结果:

export function secondFunction(id: string): Promise<UserId> {
  return thirdFunction(id)
  .then((data: TableInfo) => {
    if (Object.keys(data).length !== 3) {
      throw new Error('data in database is not mapped properly');
    }
    return getUserId(data);
  });
}

export function thirdFunction(id: string): Promise<TableInfo> {
  let query = `/* query goes here */`;
  return db.executeQuery(query, [id])
  .then((data: TableInfo) => {
    if (Object.keys(data).length < 1) {
      throw new NoResultError('some message here');
    }
    return data;
  });
}