javascript – 如何更改嵌套for循环中的promises?

这是我的一个功能的热点.这将从csv文件中获取模型变体(在数组中作为字符串)(此文件的路径取决于我们从其他csv文件中获取的文本,因此循环).

您看到的csvService.getCsvAsArray调用将获取一个包含csv文件内容的对象,其中每个列都存储在名为top column的属性下的数组中.这工作正常,所以只要知道当你看到像result [“NavigationSectionShortNames”]这样的东西时,它只是一个字符串数组.

    var INDEX_OF_PRODUCTS_SECTION = 1;
    var getAllModelVariants = function () {
        return csvService.getCsvAsArray("Contents/Sections/" + navFileNames[INDEX_OF_PRODUCTS_SECTION] + "/order.csv").then(function (result) {
            var products = [];
            for (var i = 0; i < result["NavigationSectionShortNames"].length; i++) {
                csvService.getCsvAsArray("Contents/Sections/" + navFileNames[INDEX_OF_PRODUCTS_SECTION] + "/" + result["NavigationSectionShortNames"][i]
                + "/order.csv").then(function (productModelInfo) {
                    var productFamilies = []; //array of all different families for a certain product
                    for (var j = 0; j < productModelInfo["NavigationSectionShortNames"].length; j++) {
                        csvService.getCsvAsArray("Contents/Sections/" + navFileNames[INDEX_OF_PRODUCTS_SECTION].length + "/" + result["NavigationSectionShortNames"][i] + "/" + productModelInfo["NavigationSectionShortNames"][j] + "/order.csv").then(function (modelVariants) {
                            var productModels = []; //array of all different model types for a certain family
                            for (var k = 0; k < modelVariants.length; k++) {
                                productModels.push(modelVariants["NavigationSections"][k]);
                            };
                            productFamilies.push(productModels);
                        });
                    };
                    products.push(productFamilies);
                });

            };
        })
        return products;
    };

显然,这不起作用,因为在解析promise时,递增变量(i,j或k)已经改变.是否成功使用嵌套for循环中的promises?我遇到了$q.all但我正在努力弄清楚如何将它应用到我的函数中.我目前正在研究this example,它在单个for循环中使用promises,我将尝试扩展它.

我的愿望是返回一个3D数组(例如,请参阅问题底部的plunker).

如果它有帮助,这里是这个功能的简化版本,带有静态数据,没有承诺:

    var getAllModelVariantsTest = function () {
        var result = ["productFamily1", "productFamily2", "productFamily3"];
        var testArray = ["productFamilyModel1", "productFamilyModelt2", "productFamilyModel3", "productFamilyModel4"];
        var testArray3 = ["productFamilyModelVariant1", "productFamilyModelVariant2", "productFamilyModelVariant3", "productFamilyModelVariant4"];
            var products = [];
            for (var i = 0; i < result.length; i++) {
                    var productFamilies = []; //array of all different families for a certain product
                    for (var j = 0; j < testArray.length; j++) {
                            var productModels = []; //array of all different model types for a certain family
                            for (var k = 0; k < testArray3.length; k++) {
                                productModels.push(testArray3[k]);
                            };
                            productFamilies.push(productModels);
                    };
                products.push(productFamilies);
            };
            return products;
    };
    var testOutput = getAllModelVariantsTest();

Here it is in plunker form

如果你运行它,你可以看到我希望用上面的函数输出什么样的输出的例子.

我想知道如何在嵌套for循环中使用promises获得我的第一个函数,就像plunker中的版本一样.有没有办法通过增加计数器变量和承诺来做到这一点?

是$q.all还有什么路要走?

非常感谢您的宝贵时间.如果您需要其他任何内容或者我不清楚,请告诉我.

最佳答案 回调地狱或毁灭金字塔解决方案:

function fatchAllDataForProduct(product) {

  var getProductFamilies = (product) => Promise.resolve(["productFamily1", "productFamily2", "productFamily3"]);
  var getFamilyModels    = (productFamily) => Promise.resolve(["productFamilyModel1", "productFamilyModelt2", "productFamilyModel3", "productFamilyModel4"]);
  var getModelVariants   = (familyModel) => Promise.resolve(["productFamilyModelVariant1", "productFamilyModelVariant2", "productFamilyModelVariant3", "productFamilyModelVariant4"]);
  var processVariant     = (modelVariant) => modelVariant;
  var mapFunArray = ( fun ) => (array) => array.map( fun ); // mapFunArray( e => e )( [1,2,3,4] )

  return getProductFamilies(product)
    .then( pfs => pfs
      .map( pf => getFamilyModels(pf)
        .then( fms => fms
          .map( fm => getModelVariants(fm)
            .then( mvs => mvs
              .map( processVariant )
            )
          )
        )
      )
    );
}

fatchAllDataForProduct('foobarProduct').then(
  results => {
    console.log(results);
  }
);

getFoos返回Promise.
然后我们再调用它返回另一个Promise.
在里面我们调用foos.map(.. getBars().然后..)返回promises数组.
在里面我们调用bars.map(.. getGoos.then ..).
Goos承诺反过来决定结果.

你得到的是(*表示数组):

productPromise:
  *familyPromise:
    *modelsPromise:
      *processedVariant

要摆脱Callback Hell问题,您可以使用EcmaScript7的async / await功能,今天可以使用像Babel这样的转发器.

async function fatchAllDataForProduct(product) {

  var getProductFamilies = (product) => Promise.resolve(["productFamily1", "productFamily2", "productFamily3"]);
  var getFamilyModels    = (productFamily) => Promise.resolve(["productFamilyModel1", "productFamilyModelt2", "productFamilyModel3", "productFamilyModel4"]);
  var getModelVariants   = (familyModel) => Promise.resolve(["productFamilyModelVariant1", "productFamilyModelVariant2", "productFamilyModelVariant3", "productFamilyModelVariant4"]);
  var processVariant     = (modelVariant) => modelVariant;

  var pfs = await getProductFamilies(product);
  var promises = pfs.map( async(pf) => {
    var fms = await getFamilyModels(pf)
    return fms.map( async(fm) => {
      var mvs = await getModelVariants(fm);
      return mvs.map( processVariant )
    })
  });
  return Promise.all(promises);
}

fatchAllDataForProduct('foobar').then(
  results => {
    for(var promise of results) {
      promise.then(...)
    }
  }
);
点赞