【问题标题】:fetching each item inside an array获取数组中的每个项目
【发布时间】:2021-04-01 04:50:54
【问题描述】:

所以我很确定这与Promise.all 或类似的东西有关,但我不知道该怎么做。如果有人可以帮助我解决此代码,将不胜感激。

注意:如果重要的话,我要映射的数组是一个对象数组

const productsArray = this.cartProducts.map(product => 
      fetch(`/api/products/getDetails/${product.clientId}`))
      .then(res => res.json())
      .then(data => {
        console.log(data)
      })

我什至无法启动此代码,但我不确定我应该做什么...

这是我在 Visual Studio 代码中的错误。

property 'then' does not exist on type 'promise<response>[]'

【问题讨论】:

    标签: javascript angular promise fetch promise.all


    【解决方案1】:

    TL;DR:将数组中的每个项目映射到一个 fetch 调用并将它们包装在 Promise.all() 周围。

    Promise.all(
      this.cartProducts.map(p =>
        fetch(`/api/products/getDetails/${p.clientId}`).then(res => res.json())
      )
    ).then(products => console.log(products));
    

    说明

    fetch() 返回一个Promise 又名“我保证我会在未来给你一个价值”。时机成熟时,该未来值将解析并传递给.then(callback) 中的回调以进行进一步处理。 .then() 的结果也是 Promise,这意味着它们是可链接的。

    // returns Promise
    fetch('...')
    // also returns Promise
    fetch('...').then(res => res.json())
    // also returns Promise where the next resolved value is undefined
    fetch('...').then(res => res.json()).then(() => undefined)
    

    所以下面的代码将返回另一个Promise,其中解析的值是一个解析的Javascript对象。

      fetch('...').then(res => res.json())
    

    Array.map() 将每个项目映射到回调的结果,并在所有回调执行后返回一个新数组,在本例中为Promise 的数组。

    const promises = this.cartProducts.map(p =>
      fetch("...").then(res => res.json())
    );
    

    调用map后,你会有Promise的列表等待解析。它们包含从服务器获取的实际产品价值,如上所述。但是您不想要承诺,您想要获得最终解析值的数组。

    这就是Promise.all() 发挥作用的地方。它们是 Array.map() 的承诺版本,它们使用 Promise API 将每个 Promise“映射”到解析的值。

    因为Promise.all() 将在promises 数组中的所有 个单独的promise 都已解决之后再解决另一个新的Promise

    // assuming the resolved value is Product
    
    // promises is Promise[]
    const promises = this.cartProducts.map(p =>
      fetch("...").then(res => res.json())
    );
    
    Promise.all(promises).then(products => {
      // products is Product[]. The actual value we need
      console.log(products)
    })
    

    【讨论】:

      【解决方案2】:

      William Wang 的回答非常好,但您可能想使用 async/await 来喜欢这样:

      const productsArray = this.cartProducts.map(async product => {
            const res = await fetch(`/api/products/getDetails/${product.clientId}`);
            const data = res.json();
            return data;
      });
      

      可以简化为:

      const productsArray = this.cartProducts.map(async product => {
            return await fetch(`/api/products/getDetails/${product.clientId}`).json();
      });
      

      但是请注意,这种模式将比使用 Promise.all 模式更“同步”,因为每个产品只有在获取前一个产品之后才会被获取。 Promise.all 将并行获取所有产品。

      【讨论】:

      • map() 中的异步等待无法按预期工作。
      • 你能详细说明一下吗?是我的 sn-p 吗?还是一般?我已经使用过这种模式几次,据我记忆,它一直有效。
      【解决方案3】:

      fetch() 结果是承诺,所以你需要使用Promise.all()

      const promises = await Promise.all(this.cartProducts.map(product => fetch(`/api/products/getDetails/${product.clientId}`))
      const productsArray = await Promise.all(promises.map(p => p.json()))
      

      【讨论】:

      • 谢谢,这正是我想要的!它工作得很好,但是在它工作之前我得到了一个 400 stauts 错误......不知道为什么
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-13
      • 1970-01-01
      • 2019-10-11
      • 1970-01-01
      • 2014-08-10
      相关资源
      最近更新 更多