Функция выполняется до того, как - PullRequest
0 голосов
/ 14 мая 2019

У меня есть веб-страница, которая прослушивает некоторые нажатия кнопок.Одна из кнопок («generateReport») возвращает 1 строку данных в контейнер, а другая («generateReporFromRange») возвращает диапазон строк в контейнер.Кнопка диапазона, по сути, является единственной в цикле for.

Затем у меня есть другая функция ("pBuyGauge"), которая в значительной степени создает радиальный датчик HTML / CSS, используя массив для вычисления среднего значения.Моя проблема в том, что массив «myArr» и переменная «Average» в функции pBuyGauge возвращают пустой массив и нулевое значение соответственно, но только при первом нажатии кнопки диапазона!Если я нажму еще раз, он вычислит значения.Я думал, что вызов pBuyGauge в конце цикла for в generateReportFromRange будет означать, что он имеет значения в массиве.Но, похоже, рассчитывает сам по себе, прежде чем что-либо еще.

<script>                       

export default {
  name: "pmReport",
  components: { myTable, appShell },

  data() {
    return {
      error: null,
      jobNumber: null,
      jobRangeMin: 0,
      jobRangeMax: 0,
      rowData: [],
      pBuyArr: []
    };

  },

  methods: {

    generateReportFromRange() {

      let jobIds = range(this.jobRangeMin, (this.jobRangeMax+1));

      jobIds.forEach(id => {

        this.error = "Loading..."; // show loading status in error indicator
        this.generateReport(id.toString());
        this.error = "Loading..."; // show loading status in error indicator

      });

      this.error = ""; // clear error on completion
      this.jobRangeMin = 0;
      this.jobRangeMax = 0;

      this.pBuyGauge();

    },

    generateReport(id = null) {

      fetch("/api/pm", {
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json"
        },
        credentials: "include",
        method: "POST",
        body: JSON.stringify({
          jobnum: id || this.jobNumber,
          user: this.$store.state.user
        })

      })
        .then(r =>
          r.json().then(json => {
            if (!json["Job Number"]) {
              this.error = "You do not have access to the specified record.";
              return;
            }


            this.error = "";
            this.cleanNumbers(json);
            this.columnNames(json);

            this.pBuyArr.push(parseInt(json["Percent Buy"])); //For some reason it's important this line is here and not above

            console.log("RRROp", r)

          })
        )
        .catch(e => {
          console.error("PM Fetch error", e); // eslint-disable-line
          this.error = e.message;
        });

    },

    pBuyGauge() {

      let myArr = this.pBuyArr; ////ALWAYS EMPTY FIRST TIME

      var pBuy = 0;
      var total = 0;
      var i=0;
      var average = 0;

      for(i = 0; i < (myArr.length); i++) {

          pBuy = myArr[i];
          total = total + pBuy;
      }

      average = total / myArr.length;

      console.log(JSON.stringify(myArr))
      console.log("My avg is:", JSON.stringify(average))

      var cf = 943;

      if (average >= 21) {

        var semi_cf = 0;

      }else if (average <= 0){

        var semi_cf = 707;

      }else{    

        var semi_cf = 707-(average*33.67);

      }

      document.querySelector('#mask').setAttribute("stroke-dasharray", semi_cf + "," + cf);

    }

  },

1 Ответ

0 голосов
/ 14 мая 2019

Вы звоните fetch(), что является асинхронным.Запустит запрос к серверу в фоновом режиме.В то же время ваш код продолжает выполнение, и к тому времени ваш массив будет пустым.Когда-нибудь в будущем вызов будет завершен и перезвонит, возвращенное обещание будет выполнено, и обратный вызов .then, связанный с ним, будет выполнен.Поэтому массив будет заполнен когда-нибудь.Теперь вы хотите дождаться продолжения до этой точки где-то в будущем.Для этого, прежде всего, соберите все обещания, вернув их из своего обещания и сохранив их в массиве:

  generateReport(id = null) {
   return fetch("/api/pm", {
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json"
    },
    credentials: "include",
    method: "POST",
    body: JSON.stringify({
      jobnum: id || this.jobNumber,
      user: this.$store.state.user
    })
  })
  .then(r => r.json())
  .then(json => {
    if (!json["Job Number"]) {
       // proper error handling involves rejecting the promise:
       throw new Error("You do not have access to the specified record.");
    }
    /*this.cleanNumbers(json);
    this.columnNames(json); Should this function really cause side effects ? */

   return parseInt(json["Percent Buy"]); // Thats what the returned promise chain resolves to
  });
 }


 //...
const promises = [];

 this.error = "Loading..."; 

jobIds.forEach(id => { 
    promises.push(this.generateReport(id.toString()));        
});

Теперь, когда у нас есть массив обещаний, мы можем вызвать на нем Promise.all, который превратит массив обещаний в одно обещание, содержащее результаты обещаний:

  Promise.all(promises).then(result => {
    console.log(result); // << thats what you are looking for
    //... your code to work with the result
 });
...