首页 > 解决方案 > 检查承诺的类型(使用 void 与否?)

问题描述

对于返回 Promise 的通用请求函数。你应该如何处理捕获?

感觉好像我应该有'无效'。但是随后拾取这些值会产生错误。

const request = async function<T>(url: string, context = ''): Promise<T | void> {
  return fetch(url)
    .then(res => res.json() as Promise<T>)
    .catch(err => {
      // this part is void?
      console.warn('Failed to load fetch.');
    });
};

const params = await request<{ relations: { name: string; }[] } | void>('https://www.example.com');

params.relations.filter(( relation ) => {
  console.log(relation);
});

// Error:
// Property 'relations' does not exist on type 'void | { relations: { name: string; }[] }'.
// Property 'relations' does not exist on type 'void'.

标签: typescript

解决方案


由于request将拒绝转换为履行undefined,因此在调用它时需要一个守卫,例如:

const params = await request<{ relations: { name: string; }[] } | void>('https://www.example.com');
if (!params) {
    // It didn't work
} else {
    params.relations.filter(( relation ) => {
        console.log(relation);
    });
}

但是,通常最好不要将拒绝转换为履行,以便调用者可以用try/catch或让拒绝传播等来区分它们。这对于async函数特别有用(鉴于您使用 ,您似乎正在使用它await,因为拒绝传播就像扔的东西throw一样。

所以我会删除那部分request,这也可以让你删除| void

const request = async function<T>(url: string, context = ''): Promise<T> {
  return fetch(url)
    .then(res => res.json() as Promise<T>);
};

那么使用的时候就不需要守卫了,| void调用的时候也不要在类型参数中使用:

const params = await request<{ relations: { name: string; }[] }>('https://www.example.com');

params.relations.filter(( relation ) => {
    console.log(relation);
});

游乐场链接


旁注:该代码正在成为fetchAPI 的猎物:fetch仅拒绝其对网络错误的承诺,而不是 HTTP 错误。您必须自己检查 HTTP 是否成功:

const request = async function<T>(url: string, context = ''): Promise<T> {
  return fetch(url)
    .then(res => {
        if (!res.ok) {
            throw new Error("HTTP error " + res.status);
        }
        return res.json() as Promise<T>;
    });
};

推荐阅读