代码之家  ›  专栏  ›  技术社区  ›  David Trinh

js生成器存在异步问题,并承诺不会返回结果

  •  0
  • David Trinh  · 技术社区  · 7 年前

    我遇到了另一个异步问题,我迷失了方向,不知道在哪里或如何修复它。请原谅我的恶名。

    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;
      }
    };
    

    我能够从batchFetchingGeneratorWrapper中控制batchArray中的结果,但我无法对其进行操作,我知道这与异步有关,并且还需要解决它。

    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 回复  |  直到 7 年前
        1
  •  1
  •   Roamer-1888    7 年前

    据我所知,问题主要在于 batchFetchingGeneratorWrapper()

    这应该是一个问题:

    • 固定 delay()
    • 进行适当的返回以使递归工作
    • 确保函数返回 Promise

    几乎毫无疑问(语法上)更简单 async / await 但这里是老式的thens:

    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);
    });
    
    推荐文章