为什么在打印时我从循环中的 API 调用中获得空值

Why on printing I get value of null from API call in Loop

COIN LIST 是一组加密货币 (["BTCUSDT",...])。我尝试使用 getRSI 中的 getPriceAction 和 RSI 获取价格,当我尝试控制台数据时,这两个函数正在工作。但是当我尝试在循环完成后打印响应时。它打印空数组,并且该数组的长度为 0。我想将 DATA 对象(由 SYMBOL、收盘价和 RSI 组成)存储为响应数组中的一个元素

 import { COIN_LIST } from "./COIN_LIST.js";
    import { getPriceAction } from "./PRICE_ACTION.js";
    import { getRSI } from "./RSI.js";

async function main() {
  try {
    let response = await [];
    await COIN_LIST.forEach((element, i) => {
      setTimeout(() => {
        let data = { symbol: element };
        getPriceAction(element, "4h").then((res) => {
          data.closingPrice = res;
          getRSI(res).then((res) => {
            data.RSI = res.reverse();
            data.closingPrice = data.closingPrice.reverse();
            response.push(data);
            console.log(data)
          });
        });
      }, i * 1000);
    });
    console.log(response);
  } catch (error) {
    console.log(error.message);
  }
}
main();

循环完成后,promise 还没有得到解决,这就是它打印一个空数组的原因。 实现您需要的一种方法是使用 await for(...),或者等待所有承诺得到解决,然后打印结果。

import { COIN_LIST } from "./COIN_LIST.js";
import { getPriceAction } from "./PRICE_ACTION.js";
import { getRSI } from "./RSI.js";

async function main() {
  try {
    let response = []; //---> don't need that `await`
    const promises = []; //---> array of promises
    COIN_LIST.forEach((element, i) => {
      setTimeout(() => {
        let data = { symbol: element };
        const promise = getPriceAction(element, "4h").then((res) => {
          data.closingPrice = res;
          getRSI(res).then((res) => {
            data.RSI = res.reverse();
            data.closingPrice = data.closingPrice.reverse();
            response.push(data);
            console.log(data)
          });
        });
        promises.push(promise) //---> save the reference to a promise
      }, i * 1000);
    });
    await Promise.all(promises) //---> await for all promises to be resolved, then print the result
    console.log(response);
  } catch (error) {
    console.log(error.message);
  }
}
main();

如果您想在代码中正确使用 async/await,请使用 async/await,也不要使用 .then/.catch

一些显着变化

没有增加秒数的 setTimeout ... 在获得下一个结果之前等待 1 秒 - 更清晰,如果一个请求恰好需要更长的时间,你不会以两个请求结束立即(如果 API 速率受限,这可能是个问题)

.then ... 使用 async/await.then/.catch - 在一个函数中很少需要两者

不要将 forEach 与 async/await 一起使用 ...不妨使用 .map 代替!那么你可以 await Promise.all(xxx.map(.....)) - 但这对并发请求很有用,而不是像你的代码那样对串行请求有用

import { COIN_LIST } from "./COIN_LIST.js";
import { getPriceAction } from "./PRICE_ACTION.js";
import { getRSI } from "./RSI.js";

async function main() {
    try {
        const wait = (ms) => new Promise(resolve => setTimeout(resolve, 1000));
        let response = []; //---> don't need that `await`
        for (let element of COIN_LIST) {
            let data = { symbol: element };
            data.closingPrice = await getPriceAction(element, "4h");
            const res = await getRSI(data.closingPrice);
            data.RSI = res.reverse();
            data.closingPrice = data.closingPrice.reverse();
            response.push(data);
            console.log(data);
            await wait(1000);
        }
        console.log(response);
    } catch (error) {
        console.log(error.message);
    }
}
main();

await wait(1000) 可以根据 API 的速率限制进行调整...如果速率限制适用于发出请求的时间,您可以制作一个智能的功能请求之间的延迟。

这种方式的代码假定速率限制基于上一个响应与下一个请求之间的时间间隔。