变量未在循环中更新正确

时间:2013-08-20 21:07:47

标签: javascript node.js coffeescript

我一直在使用coffeescript中的node.js来从reddit.com的json界面中提取一些故事,但却遇到了一些障碍。

我想从http://www.reddit.com/r/programming/.json解析json,然后追加一个带有参数countafter的查询语句并重新分析。根据传递给get_stories()

的参数重复

当我以file.js > test.txt运行下面的代码时,我得到了意想不到的结果。 (见下文)看起来querystring.count正在更新,但它们都匹配最后一个传递中的网址。不知道为什么我没有看到count = 0,25,50,75,125。此外,网址上不存在querystring.after。发生了什么事?

代码:

# Requires
request = require 'request'
qs = require 'querystring'
mongojs = require 'mongojs'

# Connect to db
db = mongojs 'mongodb://localhost/feedtraining', ['subreddit_stories']

get_stories = (subreddit, {per_page, pages}, storyCallback) ->
    current_page = 0
    querystring = {}

    while true
        querystring.count = current_page * per_page

        request_uri = "http://www.reddit.com/r/#{subreddit}/.json?#{qs.stringify querystring}"

        request
            uri: request_uri,
            json: true,
            (error, response, body) ->
                if !error and response.statusCode == 200
                    for item in body.data.children
                        if item.data.selftext_html is null
                            storyCallback request_uri, current_page, item.data

                    querystring.after = body.data.children[body.data.children.length-1].id
                else
                    console.log error

                return

        if current_page == pages then break else current_page++

    return

get_stories 'programming', {per_page: 25, pages: 5}, (request_uri, page, story) ->
    db.subreddit_stories.insert(story)
    console.log request_uri

输出:

http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125
http://www.reddit.com/r/programming/.json?count=125

1 个答案:

答案 0 :(得分:1)

[修改

如果您需要链接异步操作,例如为下一个querystring.after设置request,则无法使用while。循环将运行完成,在任何request完成之前启动它们,并且可以设置querystring.after

您可以使用function作为 continuations 重写迭代,以便每个请求都等到前一个请求中的after可用。

附注:由于after应该已经移动了集合的开头,因此您可能希望保持count相同的值。否则,集合的大小将随着每个请求而增长。

get_stories = (subreddit, {per_page, pages}, storyCallback) ->
    current_page = 0

    send_next_request = (querystring = {}) ->
        querystring.count = per_page

        request_uri = "http://www.reddit.com/r/#{subreddit}/.json?#{qs.stringify querystring}"

        request
            uri: request_uri,
            json: true,
            (error, response, body) ->
                if !error and response.statusCode == 200
                    for item in body.data.children
                        if item.data.selftext_html is null
                            storyCallback request_uri, current_page, item.data

                    current_page++
                    if current_page < pages
                        send_next_request(after: body.data.children[body.data.children.length-1].id)

    send_next_request()

[原始

您需要在request_uri附近创建closure

request_uri = "http://www.reddit.com/r/#{subreddit}/.json?#{qs.stringify querystring}"

do (request_uri) ->
  request
    url: request_uri,
    # ...

JavaScript,反过来CoffeeScript,没有(yet)具有块作用域,因此只为整个循环创建了1 request_uri,并且只能保留1个值。

添加request是异步的,while true循环将在之前运行完成:

storyCallback request_uri, current_page, item.data
对任何请求评估

。而且,此时request_uri将始终具有循环中给出的最后一个值。

闭包创建了一个额外的function范围,因此while true的每次迭代都可以拥有自己的request_uri


这在Loops and Comprehensions

下记录
  

当使用JavaScript循环生成函数时,通常会插入一个闭包装,以确保循环变量被关闭,并且所有生成的函数不只是共享最终值。 CoffeeScript提供do关键字,它立即调用传递的函数,转发任何参数。

for filename in list
  do (filename) ->
    fs.readFile filename, (err, contents) ->
      compile filename, contents.toString()