不要在循环中执行功能no-loop-func Axios请求异步等待

时间:2018-11-28 19:13:46

标签: javascript ecmascript-6 async-await axios es6-promise

我有一个axios请求文件,该文件可以获取许多请求,而我在所有请求周围都使用了异步功能,这样我可以每秒延迟发送到api的请求(其速率限制)。

我的代码:

import axios from 'axios';

export const litecoinApi = async (addresses, resolve, reject) => {
  let addressesBalance = {};
  let addressRequests = [];

  addresses.forEach(address => {
    addressRequests.push("https://api.blockchair.com/litecoin/dashboards/address/" + address);
  });

  function delay() {
    return new Promise(resolve => {
      setTimeout(() => resolve(), 2000);
    });
  }

  let i;
  for (i = 0; i < addressRequests.length; i++) {
    await axios.get(addressRequests[i])
    .then((res) => {
      console.log(res.data.data);
      const data = res.data.data[addresses[i]];
      console.log('data', data.address.balance);
      addressesBalance[addresses[i]] = data.address.balance / 100000000;
    }).catch((error) => {
      console.log(error);
    });
    await delay();
  }

  resolve(addressesBalance);


  // let i;
  // for (i = 0; i < addressRequests.length; i++) {
  //   await axios.get(addressRequests[i])
  //   .then((res) => {
  //     const data = res.data.data;
  //     console.log(data);
  //     addressesBalance[data.address.toString()] = data.confirmed_balance.toString();
  //   }).catch((err) => {
  //     console.log(err.response);
  //   });
  //   await delay();
  // }

  // resolve(addressesBalance);
};

我只是访问请求并遍历对象以接收(地址余额)。

我在控制台中收到警告:

./src/apis/litecoin.js
  Line 20:  Don't make functions within a loop  no-loop-func

我遇到的问题是第20行:

.then((res) => {

实际上不是问题,很明显是第22行:

const data = res.data.data[addresses[i]];

addresses只是一个字符串数组。当我从对象res.data.data中删除访问关键地址[i]时,警告消失了。控制台中的对象res.data.data是:

{LWcXUB6ny88tK49TK1V6KprE5oDcJ1zJhx: {…}}
   LWcXUB6ny88tK49TK1V6KprE5oDcJ1zJhx:
      address:
         {type: null, script_hex: "", balance: 0, balance_usd: 0, received: 0, …}
      transactions:
         []

因此莱特币地址LWcXUB6ny88tK49TK1V6KprE5oDcJ1zJhx是对象中的键,而值是另一个具有地址和事务作为键的对象。我的最终目标是平衡地址键的值。

我在下面留下了一个注释的for循环(这是针对稍有不同的api)的,因为在该循环中我没有得到警告。问题在于,如果没有通常访问对象中密钥的方式,根本无法访问litecoin地址密钥的值。

我已经更改了这一行:

const data = res.data.data[addresses[i]];

收件人:

const data = res.data.data;
const address = Object.keys(data);

当我尝试Object.keys时,我得到了错误,更不用说实际访问第一个键了:

address[0]

这使我完全不知所措,因为那样一来,我将无法访问该对象,而不会得到我在函数中使用循环的错误。

解析和拒绝来自承诺调用此函数的承诺,我使用async函数等待所有api请求完成,然后再解析此函数存在的承诺。

然后,那个诺言消失了,并正确设置了我的状态。

有人有什么想法吗?我看了很多其他的文章,但是似乎没人在解决我在这里的问题。老实说,我根本看不到循环中如何使用函数。

访问对象中的键当然不是我所知道的功能。

该:

.then((res) => {
   ...
}

只是在等待axios.get承诺。此get / then周期已在其他api请求中起作用,而没有出现此问题。另外,警告仅在尝试将密钥传递给for循环内的对象时才会发生。

我应该通知您一切正常,并显示警告。我无法摆脱这个警告,这真是令人生气。

非常感谢您的时间和见识。

2 个答案:

答案 0 :(得分:1)

根据Teemu的建议(如果您想重新发布此答案,我会给您答案)。

我尝试过:

import axios from 'axios';

export const litecoinApi = async (addresses, resolve, reject) => {
  let addressesBalance = {};
  let addressRequests = [];

  addresses.forEach(address => {
    addressRequests.push("https://api.blockchair.com/litecoin/dashboards/address/" + address);
  });

  function delay() {
    return new Promise(resolve => {
      setTimeout(() => resolve(), 2000);
    });
  }

  function axiosRequest(addressRequests, addresses) {
    axios.get(addressRequests)
    .then((res) => {
      console.log(res.data.data);
      const data = res.data.data[addresses];
      console.log('data', data.address.balance);
      addressesBalance[addresses] = data.address.balance / 100000000;
    }).catch((error) => {
      console.log(error);
    });
  }


  let i;
  for (i = 0; i < addressRequests.length; i++) {
    await axiosRequest(addressRequests[i], addresses[i]);
    await delay();
  }

  resolve(addressesBalance);
};

只需将axios请求移至其自己的函数中,然后将其传递给请求和地址即可。

await无法在axiosRequest()函数中工作,但是您仍然可以在for循环中使用它来解决问题。

这解决了我的问题,非常感谢Teemu!

答案 1 :(得分:1)

您可以同时尝试一些简单且单一的过程:

import axios from 'axios';

export const litecoinApi = async (addresses) => {
    const balance = {};

    for (const address of addresses) {
        const currentAddress = `https://api.blockchair.com/litecoin/dashboards/address/${address}`;
        const result =  await axios.get(currentAddress)
        const data = result.data.data[address];
        console.log(data);
        balance[address] = data.address.balance / 100000000;
    }

    return balance;
}

或者您可以并行处理所有请求:

const result = await Promise.all(promises);