循环使用Casperjs中的URL

时间:2015-01-09 00:53:08

标签: coffeescript casperjs

我正在尝试使用Casperjs按顺序打开几个URL。

以下是我实际代码的简化版本。

casper = require('casper').create()
casper.start()

casper.then () ->
  items = ['http://www.google.com', 'http://www.yahoo.com']

  for item, idx in items
     this.open item
     this.then ((idx) ->
        () ->
            this.capture idx + '.png')(idx)

casper.run()

在我的实际代码中,items数组是在运行时生成的。我希望这段代码能提供google.com和yahoo.com的截图,但实际上这两个屏幕截图最终都是yahoo.com。我觉得这与在循环中创建闭包有关,但我看不出如何。调用open时,item引用特定字符串。我永远不会关闭它,是吗?

1 个答案:

答案 0 :(得分:1)

问题是casper.open没有添加步骤,因此它不是异步的(如thenOpen)。它立即在外部then内执行。但是以下then 异步的,因此添加其步骤以在当前步骤(外部then)之后执行。两个open都被执行,但两个then的回调都在最后open之后执行。

因此解决方案是使用thenOpen作为组合异步步骤。 Straigt正向解决方案存在一些问题:

  

CoffeeScript is a little language that compiles into JavaScript.

这意味着JavaScript误解适用。这是一个:JavaScript closure inside loops – simple practical example

for item, idx in items行仍为for loop in JavaScript。 JavaScript具有函数级别范围,casper.then是一个异步步骤函数,这意味着所有casper.then调用的回调在循环完全运行后执行(更确切地说,在当前步骤完成之后或之后)已调用casper.run,但casper.open会立即执行。

解决方案:将casper.opencasper.then合并到casper.thenOpen并通过IIFE传递itemidx,以便将它们固定到每次迭代:

for item, idx in items
    ((item, idx) ->
        casper.thenOpen item, () ->
            this.capture idx + '.png'
    )(item, idx)

或使用Array.prototype.forEach

items.forEach (item, idx) ->
    casper.thenOpen item, () ->
        this.capture idx + '.png'