首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >迭代迭代中的setTimeout

迭代迭代中的setTimeout
EN

Stack Overflow用户
提问于 2015-06-10 07:39:26
回答 4查看 1K关注 0票数 9

下面有代码,我想在每次迭代的setTimeout之间放置一个Myurl。有许多classes,它们每个都包含许多元素。

代码语言:javascript
复制
//Some calculations before...
var i = 0;
async.whilst(
function () {
    return i <= thefooz.length - 1;
},
function (innerCallback) {

    //Some calculations where I get classes array.

    async.forEachOfSeries(classes, function (Myurl, m, eachDone) {
        // Here I want a delay
        async.waterfall([
            function (next) {
                connection.query(
                    'SELECT * FROM mydata WHERE UrlLink=? LIMIT 1', [Myurl],
                    next
                );
            },
            function (results, fields, next) {
                if (results.length !== 0) {
                    console.log("Already Present");
                    return next();
                }
                console.log("New Thing!");
                request(options2, function (err, resp, body) {
                    if (!err && resp.statusCode == 200) {
                        var $ = cheerio.load(body);
                        //Some calculations, where I get AllLinks.
                        var post = {
                            ThisUrl: AllLinks[0],
                            Time: AllLinks[1],
                        };
                        var query = connection.query('Insert INTO mydata Set ?', post, next);
                    };
                });
            }
        ], eachDone);

    }, function (err) {
        if (err) throw err;
    });
    setTimeout(function () {
        i++;
        innerCallback();
        console.log("Done");
    }, 20000);

    //Some calculations after...

那么,我如何在async.waterfall中的每个async.waterfall之间设置延迟呢?说我要延迟5秒。我设法在每个setTimeout迭代之间设置了async.whilst,但没有在每个async.forEachOfSeries迭代之间设置。它不需要等待,而是继续循环,直到每个async.forEachOfSeries完成,然后调用async.whilst setTimeout

EDIT:队列解决方案不起作用。这个解决方案似乎只是转到下一页,下一页等等,而不是输出到我的数据库。当然,我可能会错误地应用它,但我确实试着按照示例所述的方法来做。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-06-10 08:05:04

我认为您不完全理解setTimeout是如何工作的:

代码语言:javascript
复制
(function () {
    var seconds=0;
[1,2,3].forEach(function(value) {
    setTimeout(function() {
        console.log('Showing value '+value+ 'at '+Date());
    },1000*seconds++);
})
})()

此代码为每个元素创建一个回调函数,在第二秒钟后执行。请注意JS是单线程的,所以代码真正要做的是将“执行”添加到队列中。因此,如果当前执行不停止,则不会调用回调。因此,作为第二个参数传递给setTimeout函数的时间(在millis中)只是执行该代码的最小时间。

然后,按照FIFO顺序执行这些回调。

UPDATE:下面是我解释的一个例子:

代码语言:javascript
复制
function myFunction() { 
    var test=0;
    setTimeout(function(){
        console.log("This is the current value of test: "+test); 
    }, 0);
    console.log("This is run first");
    for (var i=0;i<50;i++) {
        test++;
    }
    console.log("Main thread ending, not the callbacks will be executed");
} 

setTimeout在执行之前将等待0(零),但由于主线程尚未完成,因此无法执行。然后,当循环结束时,执行回调,发现测试为50,而不是0。

票数 2
EN

Stack Overflow用户

发布于 2015-06-10 08:05:11

首先,我们必须实现一个简单的队列

队列

代码语言:javascript
复制
function Queue() {
  var obj = {};  
  var queue = [];
  var _delay;
  
  function next() {
    // If queue is empty stops execution
    if(queue.length == 0) return;
    
    // Prepare next call to next
    setTimeout(next, _delay);
    // Take out an element from the queue and execute it.
    (queue.shift())();          
  }
  
  // Add a new function to the queue
  obj.add = function (myFunc) {
    queue.push(myFunc);
  };
  
  // Start the queue execution passing the delay between each call
  obj.run = function(delay) {
    _delay = delay;
    
    // call next function
    next();
  }
  
  return obj;
  
}

然后我们在代码中使用它

代码语言:javascript
复制
// create the queue
var myQueue = Queue();

async.forEachOfSeries(classes, function (Myurl, m, eachDone) {
  // Add the function to the queue
  myQueue.add(executeWaterfall.bind(this));
}, function (err) {
  if (err) throw err;
});

// Start the queue with 5 second delay
myQueue.run(5000);

function executeWaterfall() {
  async.waterfall([
    function (next) {
      connection.query(
        'SELECT * FROM mydata WHERE UrlLink=? LIMIT 1', [Myurl],
        next
      );
    },
    function (results, fields, next) {
      if (results.length !== 0) {
        console.log("Already Present");
        return next();
      }
      console.log("New Thing!");
      request(options2, function (err, resp, body) {
        if (!err && resp.statusCode == 200) {
          var $ = cheerio.load(body);
          //Some calculations, where I get AllLinks.
          var post = {
            ThisUrl: AllLinks[0],
            Time: AllLinks[1],
          };
          var query = connection.query('Insert INTO mydata Set ?', post, next);
        };
      });
    }
  ], eachDone);
}

这远远不是最优的,因为不管怎么说,你都掉进了所谓的“厄运金字塔”(Py金字塔of doom )。

奖金

厄运金字塔

当连续使用普通回调处理异步操作时,您将在彼此之间嵌套调用;嵌套带来了更多缩进,创建了一个金字塔(指向右侧),因此被命名为“末日金字塔”。

解决方案

在这种情况下,最好使用某种承诺模式将代码从厄运金字塔中拯救出来,并促进此类问题的解决。

票数 7
EN

Stack Overflow用户

发布于 2015-06-15 22:01:04

我不太熟悉async库,但在我看来,每次运行之后,async.waterfall都会调用eachdone,这样async.forEachOfSeries就知道它应该执行下一次迭代。假设eachdone是在没有参数的情况下调用的,我希望以下内容能够正常工作:

代码语言:javascript
复制
function executeWaterfall() {
  async.waterfall([
      ......
  ], function () { window.setTimeout(eachDone, 5000));
}

如果eachdone确实获得了参数,那么您也必须发送它们。

作为另一种选择,我希望你可以给你的瀑布再增加一步,等待5秒。这将不管eachdone的参数如何都能工作(但如果第三个瀑布函数期望有更多的副手,则可能会失败):

代码语言:javascript
复制
function executeWaterfall() {
  async.waterfall([
    function (next) {
      connection.query(
        'SELECT * FROM mydata WHERE UrlLink=? LIMIT 1', [Myurl],
        next
      );
    },
    function (results, fields, next) {
      if (results.length !== 0) {
        console.log("Already Present");
        return next();
      }
      console.log("New Thing!");
      request(options2, function (err, resp, body) {
        if (!err && resp.statusCode == 200) {
          var $ = cheerio.load(body);
          //Some calculations, where I get AllLinks.
          var post = {
            ThisUrl: AllLinks[0],
            Time: AllLinks[1],
          };
          var query = connection.query('Insert INTO mydata Set ?', post, next);
        };
      });
    },
    function (next) {
      window.setTimeout(next, 5000);
    }
  ], eachDone);
}

现在,我想再次强调,我不熟悉async,而且所有的示例都没有经过测试。也许一切都是大错特错,但这是我的直觉。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30750051

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档