JS/Vue - 返回承诺异步问题

时间:2021-05-25 06:10:58

标签: javascript vue.js asynchronous promise es6-promise

您好,感谢您花时间阅读我的问题。

我有一个 Vue 组件,称之为“interactiveChart”。在安装时(按如下所示的特定顺序),我执行以下操作:

  1. 初始化我的东西(数据库管理器、工具管理器等)

  2. 第一次调用 this.run(); 获取我的数据。 [this.run(); 调用 this.fetch(); 返回一个 Promise< /em>,根据我在highchart中对我的数据进行排序,将数据按顺序排列等等。我只是处理逻辑。所以是这样的:

    • run() ->
    • (内部运行)this.fetch->
    • then-> - 逻辑在这里- || catch-> -处理错误-->
    • (再次在内部运行) this.render() 调用渲染函数,您可以想象它渲染图表。
  3. 到目前为止一切顺利。所以,我们仍然处于挂载状态,在初始化和第一次调用 this.run() 之后,我在那里有一些事件处理程序(它们工作正常),它们侦听特定事件。在事件侦听器之后,我再次运行 this.render(),因为某些事件可能会更改图表选项(添加另一个轴等)。 但是。我们最初解析的数据基于特定的 id。假设 id 1。有些事件可能会要求另一个 id 的数据,比如说 2,3 和 4。这意味着我必须再次运行 this.run() 以获取 2,3 和 4。所以不要运行它.run() 仅用于一个 id,我使用一个名为 idNotations 的数组来存储解析数据所需的所有 id。我在 this.run() 中做了一个 for of 循环来获取每个 id 的数据。我的问题如下:

如果我给出 4 个 id,this.run() 中的 this.render() 函数将运行 4 次(所以我一直看到图表重新加载 1-2 秒)然后它正确显示。数据显示得很好。它只是在为每个 ID 获取所有数据之前渲染运行。我想要的是让它只运行一次,在所有的承诺都完成之后。如果我将 render() 移到 for of 循环之外,它就不会显示(因为 run() 不是异步的,它只是调用 fetch 以避免代码重复。我该如何解决这个问题?

  mounted() {
console.log('Function Call: mounted()');

//Initialization
this.selectedTimeSpan = timeSpansArray.find((el) => el.timeSpan == '5Y');
this.mdg2Client = globalMdg2ClientFactory.createMdg2Client();
this.highchartOptions = this.getHighchartsOptions();
this.run();

/**
 * Events Below
 */

//When Timespan Changes
this.$root.$on('chartZoom', (payload) => {
  console.log('[Event Emitted] - Timespan Changed');
  this.interactiveChart.showLoading('Loading Data..');
  this.selectedTimeSpan = timeSpansArray.find(
    (el) => el.timeSpan === payload.timeSpan
  );
  this.run();
});

//When Chart Type Changes
this.$root.$on('chart-type', (payload) => {
  console.log('[Event Emitted] - Chart Type/Data Changed', payload);

  //Reseting step
  this.hasStep = false;

  //Need yMin in OHLC and Candlestick chart types
  let yMin = toolsManager.calculateMin(
    this.highchartOptions.series[0].data
  );

  //Swap between chart types
  switch (payload['chart-type']) {
    case 'step':
      this.hasStep = true;
    case 'mountain':
      this.highchartOptions.series[0].type = null;
      this.highchartOptions.chart.type = 'area';
      this.highchartOptions.yAxis[0].min = yMin;
      break;
    case 'candlestick':
      this.highchartOptions.series[0].type = 'candlestick';
      break;
    case 'ohlc':
      this.highchartOptions.series[0].type = 'ohlc';
      break;
    default:
      this.highchartOptions.series[0].type = 'line';
      break;
  }
  this.highchartOptions.series[0].step = this.hasStep;

  //Select performance
  if (payload['chart-perf'] === 'axisTrue') {
    this.highchartOptions.plotOptions.series.compare = 'percent';
    this.highchartOptions.yAxis[0].min = null;
    this.highchartOptions.yAxis[0].labels.format = '{value:.2f}%';
  } else {
    this.highchartOptions.plotOptions.series.compare = null;
    this.highchartOptions.yAxis[0].labels.format = null;
  }

  //Benchmark selected
  if (payload['add-benchmark']) {
    if (payload['add-benchmark'].length > 0) {
      this.interactiveChart.showLoading('Loading Data..');
      this.benchmarks = payload['add-benchmark'];
      this.cleanIds();
      this.renderFlag = false;
      this.run();
      this.renderFlag = true;
    } else {
      this.cleanSeries();
      this.cleanBenchmarks();
      this.cleanIds();
    }
  }

  //Indicators selected
  if (payload['indicators']) {
    if (payload['indicators'].length > 0) {
      this.interactiveChart.showLoading('Loading Data..');
      this.indicators = payload['indicators'];
      this.sortIndicators();
    } else {
      while (this.indicators.length > 0) {
        this.indicators.pop();
      }
      this.cleanIndicators();
    }
  }

  this.render(this.highchartOptions);
});





   //Fetching Data from server
fetch(timeSpan, idToFetchFrom) {
  console.log(`Function Call: fetch()`);
  this.timespanDates = toolsManager.calculateDates(
    timeSpan.totalTimeRange.days
  );

  const data = {
    id: idToFetchFrom,
    quality: this.priceQuality,
    range: {
      start: this.timespanDates[0],
      end: this.timespanDates[1],
    },
  };

  const meta = {
    pagination: {
      limit: timeSpan.totalTimeRange.days,
    },
  };

  //If it is 1D or 5D
  if (this.selectedTimeSpan.getIntradayData) {
    data.type = 'trade';
    data.quality = 'DLY';
    data.range.start.concat('T00:00:00.000Z');
    data.range.end.concat('T07:00:00.000Z');
    data.granularity = timeSpan.granularity;

    timeSpan.timeSpan === '1D'
      ? (meta.pagination.limit *= 24 * 60) //Days * 24 Hours * 60 (1 minute granularity so 60*1M===1H)
      : (meta.pagination.limit *= 24 * 6); //Days * 24 Hours * 6 (10 minutes granularity so 6*10M===1H)

    return this.mdg2Client.requestEndpoint(
      this.requestMethod,
      '/api/v1/prices/timeSeries/intraday/subsample/list',
      { data, meta }
    );
  } else {
    return this.mdg2Client.requestEndpoint(
      this.requestMethod,
      this.endpoint,
      { data, meta }
    );
  }
},


//Handling the response from the server
run() {
  console.log('Function Call: run()');
  this.sortIndicators();
  for (let id of this.idsToFetchData) {
    console.log(`run(): ${id}`);
    this.fetch(this.selectedTimeSpan, id)
      .then((res) => {
        const { data } = res;
        let prices = [];

        //we get an array subsamples when we use the endpoint for 1D and 5D, but an array called prices for the rest of the timespans
        this.selectedTimeSpan.getIntradayData
          ? (prices = data.subsamples)
          : (prices = data.prices);
        let priceSeries = [];
        this.volumeSeries = [];
        /**
         * Tick Interval can be either 1 or 5. We get the lowest price each day or every fifth one.
         */
        if (this.selectedTimeSpan.tickInterval === 1) {
          for (let i = 0; i < prices.length; i++) {
            let xData = null;
            this.selectedTimeSpan.getIntradayData
              ? (xData = Math.floor(new Date(prices[i].time).getTime()))
              : (xData = Math.floor(new Date(prices[i].date).getTime()));
            priceSeries[i] = {
              x: xData,
              open: prices[i].first,
              high: prices[i].high,
              low: prices[i].low,
              close: prices[i].last,
              y: prices[i].last,
              volume: prices[i].tradingVolume,
            };
            if (id == this.$props.idNotation) {
              this.volumeSeries[i] = {
                x: xData,
                y: prices[i].tradingVolume,
              };
            }
          }
        } else {
          let j = 0;
          for (
            let i = 4;
            i < prices.length;
            i += this.selectedTimeSpan.tickInterval
          ) {
            priceSeries[j] = {
              x: Math.floor(new Date(prices[i].date).getTime()),
              open: prices[i].first,
              high: prices[i].high,
              low: prices[i].low,
              close: prices[i].last,
              y: prices[i].last,
              volume: prices[i].tradingVolume,
            };
            if (id == this.$props.idNotation) {
              this.volumeSeries[j] = {
                x: Math.floor(new Date(prices[i].date).getTime()),
                y: prices[i].tradingVolume,
              };
            }
            j++;
          }
        }

        if (id == this.$props.idNotation) {
          this.highchartOptions.series[0].data = priceSeries;
          this.highchartOptions.series[1].data = this.volumeSeries;
        } else {
          this.benchmarks.forEach((benchmark) => {
            if (benchmark.id == id) {
              benchmark.data = priceSeries;
              this.highchartOptions.series.push(benchmark);
            }
          });
        }

        // this.sortIndicators(this.indicators);
        this.highchartOptions.xAxis.labels.format = `{value:${this.selectedTimeSpan.xAxisDateFormat}}`;
        console.log('look', this.renderFlag);
        if (this.renderFlag) this.render(this.highchartOptions);
      })
      .catch((e) => {
        console.log('[ Caught Error ]', e);
      });
  }
},

1 个答案:

答案 0 :(得分:0)

按照 recoilnetworks 的建议使用 Promise.all() 解决。谢谢!