【问题标题】:How to load these iframes sequentially?如何按顺序加载这些 iframe?
【发布时间】:2020-01-02 06:00:12
【问题描述】:

我有一大堆字符串,每个字符串最终都应该制作/加载一个 iframe。这个想法是按顺序加载每个 iframe:iframe 1 loaded → start loading iframe 2... etc..

我想通过将数组分成块并并行运行来划分负载。但是,我不知道如何在此设置中按顺序运行每个块的内容。

  1. Chunk[0] → 加载 iframe 1 → 加载 iframe 1 → 加载 iframe 2 → 加载 iframe 2 → 完成
  2. Chunk[1] → 加载 iframe 3 → 加载 iframe 3 → 加载 iframe 4 → 加载 iframe 4 → 完成
  3. Chunk[2] → 加载 iframe 5 → 加载 iframe 5 → 加载 iframe 6 → 加载 iframe 6 → 完成
  4. Chunk[3] → 加载 iframe 7 → 加载 iframe 7 → 加载 iframe 8 → 加载 iframe 8 → 完成
  5. Chunk[4] → 加载 iframe 9 → 加载 iframe 9 → 加载 iframe 10 → 加载 iframe 10 → 完成
  6. 当所有块都完成后显示结果。

我该怎么做?

现在我的代码可以做我想做的一切,除了顺序加载:

JSFiddle

var promiseArray = [];
var urlParams = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var maxLength = urlParams.length/5;
var chunks = divideArray( urlParams, maxLength );

for ( var chunkIndex=0; chunkIndex < chunks.length; chunkIndex++) {
    var urlParams = chunks[ chunkIndex ];
  console.log( 'Chunk-' + chunkIndex );
  for ( var paramIndex=0; paramIndex < urlParams.length; paramIndex++) {

    promiseArray.push(
      new Promise((resolve, reject) => {

        var urlParam = urlParams[ paramIndex ];
        var iframe = $('<iframe src="https://gist.github.com/joonaspaakko/414c4a43ac092f562e07e1642fa75dc5.pibb?val=' + urlParam + '"></iframe>');
        iframe.prependTo('body');
        iframe.on("load", function() {
          // var iframeBody = iframe.contents().find('body');
          iframe.remove();

          console.log( 'Iframe-'+ urlParam );
          resolve( 'Iframe-'+ urlParam +' loaded.');
        });

      })
    )

  }
}


Promise.all( promiseArray ).then(function( result ) {
  console.log(result);
});


function divideArray( array, maxLength ) {
  var chunks = [];
  for ( var i=0; i < array.length; i+=maxLength ) {
    chunks.push( array.slice(i,i+maxLength) );
  }
  return chunks;
}

【问题讨论】:

    标签: javascript


    【解决方案1】:

    使用原始 Promise 链接异步操作相当麻烦,但您可以使用 async 函数来做到这一点:

    1. 将加载 iframe 的代码提取到 async 函数中
    2. 创建另一个 async 函数,为块中的每个 URL 依次调用第一个函数。
    3. 其余部分或多或少与您已经拥有的代码相同:为每个块调用块处理函数并等待它们全部使用Promise.all完成

      var promiseArray = [];
      var urlParams = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      var maxLength = urlParams.length / 5;
      var chunks = divideArray(urlParams, maxLength);
      
      for (var chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
          var urlParams = chunks[chunkIndex];
          console.log('Chunk-' + chunkIndex);
          promiseArray.push(processChunk(urlParams));
      }
      
      Promise.all(promiseArray).then(function (result) {
          console.log(result);
      });
      
      
      async function processURL(urlParam) {
          return new Promise((resolve, reject) => {
              var iframe = $('<iframe src="https://gist.github.com/joonaspaakko/414c4a43ac092f562e07e1642fa75dc5.pibb?val=' + urlParam + '"></iframe>');
              iframe.prependTo('body');
              iframe.on("load", function () {
                  console.log('Iframe-' + urlParam);
                  resolve('Iframe-' + urlParam + ' loaded.');
              });
          });
      }
      
      
      async function processChunk(chunk) {
          var urlResults = [];
          for (var paramIndex = 0; paramIndex < urlParams.length; paramIndex++) {
              var urlResult = await processURL(chunk[paramIndex]);
              urlResults.push(urlResult);
          }
          return urlResults;
      }
      
      
      function divideArray(array, maxLength) {
          var chunks = [];
          for (var i = 0; i < array.length; i += maxLength) {
              chunks.push(array.slice(i, i + maxLength));
          }
          return chunks;
      }
      

    【讨论】:

      【解决方案2】:

      使用这个方便的实用功能:

      /**
       * Given an Iterable (an array, for example), or a promise of an Iterable,
       * iterates serially over all the values in it, executing the given iterator on each element.
       *
       * @tutorial https://stackoverflow.com/a/41608207/3563013
       * @tutorial http://bluebirdjs.com/docs/api/promise.each.html
       * @tutorial https://jsfiddle.net/mckabue/zmf3tL9k/11/ - you can queue mapped promises
       *
       * @param { Iterable<any> | Promise<Iterable<any>> } items
       * @param { Function } fn
       * @param {*} options
       */
      export default function promiseEach(items, fn, options) {
          options = Object.assign({}, {
              continueOnFail: false,
              startValue: undefined,
              nonArrayError: "Non array passed to each",
              emptyArrayResolveValue: undefined
          }, options);
          // invalid input
          if (!Array.isArray(items)) {
              return Promise.reject(new Error(options.nonArrayError));
          }
          // empty case
          if (items.length === 0) {
              return Promise.resolve(options.emptyArrayResolveValue);
          }
          return items.reduce((accumulator, currentValue, currentIndex, array) => {
              return accumulator[!!options.continueOnFail ? 'finally' : 'then'](function () {
                  return fn(currentValue, currentIndex, array);
              });
          }, Promise.resolve(options.startValue));
      }
      

      见:

      function promiseEach(items, fn, options) {
          options = Object.assign({}, {
              continueOnFail: false,
              startValue: undefined,
              nonArrayError: "Non array passed to each",
              emptyArrayResolveValue: undefined
          }, options);
          // invalid input
          if (!Array.isArray(items)) {
              return Promise.reject(new Error(options.nonArrayError));
          }
          // empty case
          if (items.length === 0) {
              return Promise.resolve(options.emptyArrayResolveValue);
          }
          return items.reduce((accumulator, currentValue, currentIndex, array) => {
              return accumulator[!!options.continueOnFail ? 'finally' : 'then'](function () {
                  return fn(currentValue, currentIndex, array);
              });
          }, Promise.resolve(options.startValue));
      };
      
      promiseEach([1,2,3,4,5,6], function(i){
        return new Promise(resolve => {
          setTimeout(() => {
          console.log(i);
            resolve();
          }, 2000);
        });
      }).then(() => console.log("DONE"));

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-20
        • 2014-11-03
        • 1970-01-01
        • 2014-10-03
        • 1970-01-01
        • 2021-11-03
        • 1970-01-01
        相关资源
        最近更新 更多