【问题标题】:Sending array response in promise callback but the response is blank在承诺回调中发送数组响应,但响应为空白
【发布时间】:2019-11-07 12:48:57
【问题描述】:

我正在从谷歌地图生成图像。这是一个承诺返回方法,因为我只是循环使用结果并将结果存储到“then”回调内的新数组变量中,但响应存在但它没有显示在浏览器中。

在我的谷歌地图生成图像功能不是承诺返回函数之前,它正在向浏览器发送响应,但它是一个承诺返回函数,因此响应存在但控制器方法没有向浏览器发送响应。

  static providerMapImageGenerator(req, res) {
    let providerArr = []
    ProvidersRepository.getProviderInfoForMapImage()
      .then(providers => {
        providers.forEach(provider => {
          // Generating image against each entr
          MapGenerator.getMapImage(
            provider.latitude,
            provider.longitude,
            provider.name,
            provider.providerId
          )
            .then(res => {
              // Saving record after each entry
              ProviderMap.create({
                providerId: provider.providerId,
                url: res.Location
              })
              // Adding new array for response
              providerArr.push({
                id: provider.providerId,
                url: res.Location,
                lat: provider.latitude,
                long: provider.longitude,
                name: provider.name
              })
            })
            .catch(err => console.log(err, "err in generating image"))
        })
        // Sending final response against all generated entries to user
        res.send(providerArr) // this is going blank to the browser
      })
      .catch(error => {
        // Sending error response if fails
        res.send(error)
      })
  }

我需要在浏览器中显示 providerArr 响应。

【问题讨论】:

  • For 循环在继续下一次迭代之前不会等待异步操作完成。使用 Promise.all 并传递一组 promise 以等待它们全部完成
  • 我该如何解决这个问题?
  • @IsaacVidrine 你能告诉我如何在我当前的代码中添加 promise.all。谢谢。

标签: javascript arrays node.js promise


【解决方案1】:

您的循环无需等待承诺结果即可进行。您可以使用async/awaitfor of 循环来执行您想要的操作,如下所示:

ProvidersRepository.getProviderInfoForMapImage()
  .then(async (providers) => {
    for(provider of providers){
      // Generating image against each entr
      let image = await MapGenerator.getMapImage(
        provider.latitude,
        provider.longitude,
        provider.name,
        provider.providerId
      );
      // Saving record after each entry
      await ProviderMap.create({
         providerId: provider.providerId,
         url: res.Location
      });
       // Adding new array for response
      providerArr.push({
          id: provider.providerId,
          url: res.Location,
          lat: provider.latitude,
          long: provider.longitude,
          name: provider.name
         });
     })
    }
    // Sending final response against all generated entries to user
    res.send(providerArr) // this is going blank to the browser
  })
  .catch(error => {
    // Sending error response if fails
    res.send(error)
  })

PS:未测试

【讨论】:

  • for of 循环仅适用于对象,不适用于数组。所以这个解决方案对我不起作用。
  • 但在将 for of 转换为 for 循环后它现在可以工作了。
  • @MuhammadAdil for...of 语句创建循环迭代可迭代对象,包括:内置字符串、数组、类数组对象(例如,参数或 NodeList)、TypedArray、Map、设置和用户定义的可迭代对象。它调用一个自定义迭代钩子,其中包含要为对象的每个不同属性的值执行的语句。这是文档:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 你是对的。但我在我的代码中尝试了 for of 循环,但循环对我不起作用。不知道为什么,所以我尝试了 for 循环。
  • 我的providers结果直接来自sequelize模型。也许它不是真正的类数组对象或可迭代对象。
【解决方案2】:

Amadou 的回答是正确的,但它按顺序而不是并行进行处理,等待每个 MapGenerator.getMapImage() 完成后再触发另一个请求。通过一些修改,您可以同时触发所有请求并等待所有请求完成。

  static providerMapImageGenerator(req, res) {
    let providerArr = []
    ProvidersRepository.getProviderInfoForMapImage()
      .then(providers => {
        return Promise.all(providers.map(provider => {
          // Generating image against each entr
          return MapGenerator.getMapImage(  // ** actually return the promise so
            provider.latitude,              // ** Promise.all gets an array of promises
            provider.longitude,
            provider.name,
            provider.providerId
          )
            .then(res => {
              // Saving record after each entry
              ProviderMap.create({
                providerId: provider.providerId,
                url: res.Location
              })
              // Adding new array for response
              providerArr.push({
                id: provider.providerId,
                url: res.Location,
                lat: provider.latitude,
                long: provider.longitude,
                name: provider.name
              })
            })
            .catch(err => console.log(err, "err in generating image"))
        })
        // Sending final response against all generated entries to user
        .then(() => res.send(providerArr)); // this is going blank to the browser
      })
      .catch(error => {
        // Sending error response if fails
        res.send(error)
      })
  }

【讨论】:

  • 以上promise.all我的反应将是我想要的一样
猜你喜欢
  • 2020-08-12
  • 2016-11-28
  • 2020-09-30
  • 2020-09-10
  • 2020-09-02
  • 2019-02-22
  • 1970-01-01
  • 2016-10-25
  • 2016-12-03
相关资源
最近更新 更多