асинхронные проблемы с генератором js и обещания не возвращают результат - PullRequest
0 голосов
/ 27 апреля 2018

У меня возникла еще одна асинхронная проблема, из-за которой я потерялся и понятия не имею, где и как это исправить. Прости мое плохое наименование.

api вызывает twitch api и возвращает массив его результатов.

  exports.batchPromiseWrapper = function(arr) {
  const filteredMungedDataArr = [];

  let promiseBatachArray = arr.map(vod_id => {
    var url = `https://api.twitch.tv/kraken/videos/${vod_id.id}/markers`;
    var params = { api_version: 5 };

    return axios
      .get(url, {
        params: params,
        headers: {
          "Client-ID": "xxxxxxxxxxxxxxx"
        }
      })
      .then(res => {
        return res.data;
      })
      .catch(function(error) {
        console.log(error);
      });
  });

  return Promise.all(promiseBatachArray)
    .then(markers => {
      if (markers !== null) {
        markers.map(markerObj => {
          if (markerObj.markers.game_changes !== null) {
            markerObj.markers.game_changes.forEach(gameName => {
              if (gameName.label === "Fortnite") {
                filteredMungedDataArr.push(markerObj);
              }
            });
          }
        });
        return filteredMungedDataArr;
      }
    })
    .catch(err => {
      if (err.status === 500 || err.status === 404) {
        console.log("error: ", err, err.message);
      }
    });
};

Данные выглядят так: [[1,2,3,4,5], [1,2,3,4,5]], генератор выдаст и сделает обещание. Все вызовят 5 перед паузой 5сек и продолжением до следующей партии 5.

exports.batchFetchingGeneratorWrapper = function(generator, batchArray) {
  let evalNextValue = generator.next();

  let delay = (v, t) => {
    return new Promise(resolve => {
      setTimeout(resolve.bind(null, v), t);
    });
  };

  if (!evalNextValue.done) {
    exports.batchPromiseWrapper(evalNextValue.value).then(data => {
      let newBatchArray = batchArray;
      if (data !== undefined) {
        newBatchArray = batchArray.concat(data);
      }

      delay(5000).then(() => {
        exports.batchFetchingGeneratorWrapper(generator, newBatchArray);
      });
    });
  } else {
    console.log("yay done!", batchArray);
    return batchArray;
  }
};

Я могу утешить результаты в batchArray из batchFetchingGeneratorWrapper, но я не могу на него воздействовать, и я знаю, что это как-то связано с асинхронностью и как это еще предстоит решить.

promiseDataWrapper
  .then(data => {
    return gatherData.cleanUpVODData(data);
  })
  .then(data => {
    function* batchFetching(batchArray) {
      for (let i = 0; i < batchArray.length; i++) {
        yield batchArray[i];
      }
    }

    let batchArrResult = [];
    let g = batchFetching(data);

    new Promise((resolve, reject) => {
      gatherData.batchFetchingGeneratorWrapper(g, batchArrResult);

      if (g.done) { // i dont think this works 
        console.log("batchArrResult 1: ", batchArrResult);
        resolve(batchArrResult);
      }
    }).then(result => console.log("asdfasdf", batchArrResult)); // empty array is returned
  });

1 Ответ

0 голосов
/ 27 апреля 2018

Насколько я могу судить, проблема заключается главным образом в batchFetchingGeneratorWrapper().

Это должно быть вопросом:

  • крепление delay()
  • делает соответствующие возвраты, чтобы рекурсия работала
  • гарантирует, что функция вернет Promise.

Почти несомненно (синтаксически) проще с async / await, но здесь это со старомодными тогда:

exports.batchFetchingGeneratorWrapper = function(generator, batchArray) {
    let evalNextValue = generator.next();
    let delay = (t) => {
        return new Promise(resolve => {
            setTimeout(resolve, t);
        });
    };
    if (!evalNextValue.done) {
        return exports.batchPromiseWrapper(evalNextValue.value).then(data => {
            return delay(5000).then(() => {
                return exports.batchFetchingGeneratorWrapper(generator, batchArray.concat(data || []));
            });
        });
    } else {
        console.log("yay done!", batchArray);
        return Promise.resolve(batchArray); // <<< promise wrapped to ensure that batchFetchingGeneratorWrapper() returns Promise
    }
};

И соединить batchFetchingGeneratorWrapper() соответствующим образом:

promiseDataWrapper
.then(data => gatherData.cleanUpVODData(data))
.then(data => {
    function* batchFetching(batchArray) {
        for (let i = 0; i < batchArray.length; i++) {
            yield batchArray[i];
        }
    }
    return gatherData.batchFetchingGeneratorWrapper(batchFetching(data), []).then(batchArrResult => {
        console.log('batchArrResult: ', batchArrResult);
        return batchArrResult;
    });
}).catch(error => {
    console.log(error);
});
...