在 node.js 中做一个 while 循环,总是给我最后一个数组项

doing a while loop in node.js, always give me the last array item?

本文关键字:循环 数组 最后一个 while 一个 js node      更新时间:2023-09-26

im 使用僵尸.js库,要对 DOM 进行一些测试,我有这个脚本

Browser = require "zombie"
arr = new Array("http://yahoo.com", "http://google.com", "http://msn.com")
i = 0
while i < arr.length
    b = new Browser()
    b.visit arr[i], ->
        console.log b.text "title"
    b.close()
    i++

一切正常,但它只记录 MSN 标题两次,因此 while 循环记录数组中的最后一项两次。 我似乎看不出问题出在哪里?

您正在注册浏览器visit完成时的回调。到那时,循环已经运行完成,因此变量b指向您创建的最后一个浏览器,这意味着它的标题将是 MSN 的标题,而不是其他页面的标题。为了解决这个问题,请使用闭包:

Browser = require "zombie"
arr = new Array("http://yahoo.com", "http://google.com", "http://msn.com")
i = 0
createBrowser = (url) ->
    b = new Browser()
    b.visit url, -> console.log b.text "title"
    b.close()
while i < arr.length
    createBrowser(arr[i++])

这是有效的,因为现在您创建的每个浏览器都有一个单独的范围,以及一个单独的浏览器变量。

或者,使用 ZombieJS 的 visit 函数的回调参数:

Browser = require "zombie"
arr = new Array("http://yahoo.com", "http://google.com", "http://msn.com")
i = 0
while i < arr.length
    b = new Browser()
    b.visit arr[i], (e, myBrowser) ->
        console.log myBrowser.text "title"
    b.close()
    i++

我认为您要做的是以下内容(警告,未经测试!

Browser = require "zombie"
sites = ['http://yahoo.com', 'http://google.com', 'http://msn.com']
process = (site) ->
  b = new Browser()
  b.visit site, () ->
    title = b.text title
    console.log title
    b.close()
process site for site in sites

我冒昧地更改了一些零碎的东西 - 希望它仍然清晰。

JavaScript(和CoffeeScript)有奇怪的范围规则,如果你不习惯的话。我发现通常最好在一个函数中完成所有工作,以使事情按预期工作。

我不知道僵尸.js是如何工作的,但我认为这应该如你所料。

visit 方法是异步的,采用回调函数。换句话说,在任何日志记录发生之前调用 visit 三次,即控制台.log不会b.visitb.close调用之间执行。到最后一个回调完成时,b引用"最后一个"浏览器实例(msn 实例)。visit方法可能会传递回调的结果,请查看文档。

Browser = require 'zombie'
for url in ["foo", "bar", "baz"] # elegant way to loop lists in coffeescript
  b = new Browser
  b.visit url, (err, b) ->       # b given as argument masks the b in outer scope
    console.log b.text "title"
    b.close()