【问题标题】:using fetch in TypeScript results in strange behaviour在 TypeScript 中使用 fetch 会导致奇怪的行为
【发布时间】:2018-09-16 12:50:27
【问题描述】:

我在 TS 中有函数必须返回 Promise<Array<any>>,这个函数使用 fetch:

(q: any): Promise<Array<any>> => {
    return fetch('http://speedtest.net', { mode: 'no-cors' })
        .then(response => response.json())
        .then((data: any) => [data])
        .catch(error => console.error(error))
        ;
};

它会导致 TS 编译器错误:Type 'Promise&lt;void | any[]&gt;' is not assignable to type 'Promise&lt;any[]&gt;'.

Here is link to playground

  • 如果我只返回data(不是[data])- ts 没问题
  • 如果我来自 catch 块的throw new Error(error) - 对 ts 来说没问题(但对我来说不行,因为不想冒泡错误)
  • 如果我来自 catch 块的return null - 对 ts 来说没问题,但为什么我需要这样做???

PS:

  • 实际获取与提供的不同,这里是重现我的情况的最低要求
  • 不要告诉我mode 在获取中,我知道,no-cors 几乎没用,返回opaque
  • 是的,我需要跳过冒泡;是的,我需要在这里捕获块。
  • 这个对TS来说还可以,唯一的区别是data而不是[data]

    (q: any): Promise<Array<any>> => {
    return fetch('http://speedtest.net', { mode: 'no-cors' })
        .then(response => response.json())
        .then((data: any) => data)
        .catch(error => console.error(error))
        ;
    };
    

【问题讨论】:

  • 如果您返回未定义的错误。返回[]怎么样?
  • 等等为什么接受null ?!
  • 正如我所提到的,即使返回 null 也可以解决这个问题,但这里有另一个问题:为什么从那时返回数据,并从 catch 返回 console.log 结果是可以的,而返回 [data] - 破坏一切???
  • 在我提供的操场上试试 - 你会看到
  • 我猜data: any 有效地禁用了承诺类型检查,而[data] as Array&lt;any&gt; 导致了整个承诺链的类型检查。

标签: javascript typescript types promise fetch


【解决方案1】:

问题是你传递给catch的函数返回void,所以在失败的情况下,你实际上返回一个Promise&lt;void&gt;。您可以通过在记录后返回某些内容来修复它,如其他答案中所述,但这很容易出错,因为您的函数的调用者不会意识到有错误。在某些情况下这可能没问题,但我建议这样写:

你可以这样写:

(q: any): Promise<Array<any>> => {
    const promise = fetch('http://speedtest.net', { mode: 'no-cors' })
        .then(response => response.json())
        .then((data: any) => [data]);
    promise.catch(error => console.error(error));
    return promise;
};

然后代码的调用者必须自己处理失败的promise,并且可以决定要做什么。或者他们可能会忽略它,并依赖某种全局机制来捕获未处理的拒绝承诺。

请注意,console.error 保证在您的方法的调用者完成任何处理之前被调用,因为传递给then 的回调与then 调用的调用顺序相同 - 请参阅https://promisesaplus.com/#point-37

【讨论】:

    【解决方案2】:

    似乎 @Jonas W. 从评论到原始问题是正确的 (playground)

    看起来data: any 在第二个then 中禁用了类型检查,就好像我引入了interface 并使用它而不是any 它会导致几乎相同的错误。

    谢谢大家帮助我=)

    【讨论】:

      【解决方案3】:

      如果 fetch 调用失败,它将转到.catch,然后 catch 也需要返回一些东西。返回一个空数组以确保函数 always 返回一个数组。

      (q: any): Promise<Array<any>> => {
        return fetch("http://speedtest.net", { mode: "no-cors" })
          .then(response => response.json())
          .then(data => [data])
          .catch(error => {
            console.log(error)
            return []
          })
      }
      

      【讨论】:

      • 是的,正如问题中提到的那样,即使返回 null 也可以解决问题,但会产生问题:为什么从那时起返回数据,并从 catch 返回 console.log 结果是可以的,而返回 [data] - 破坏一切???
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-27
      • 2021-05-28
      • 1970-01-01
      相关资源
      最近更新 更多