【问题标题】:Piece of code that creates .json files, does not work创建 .json 文件的一段代码不起作用
【发布时间】:2016-12-25 22:50:33
【问题描述】:

我有这段代码,我需要它来从那个网站获取一些数据,即 apiurl 中的字符串。此代码需要下载这些网站,并在 json 中找到某些 appid。它需要下载这些网站上的数据并将它们存储在一个 json 文件中。由于某种原因,这不起作用。

我在 .js 文件中有这段代码:

var gamekeys = JSON.parse(fs.readFileSync('gamekeys.json'));
var jsonstring = JSON.stringify(gamekeys, null, 4);

UpdateGamePricelist();

function UpdateGamePricelist() {
	for(var i = 0;i<gamekeys.keys.length;i++) {
		appid = gamekeys.keys[i].appid;
		
		var apiurl = "http://store.steampowered.com/api/appdetails?appids="+appid;
		
		if (i < 95) {
			
			request(apiurl, function(err, response, body) {
				if (err) {
					console.log("Error when updating game prices: " + err+"\n");
					return;
				}
				
				var apiresponse = JSON.parse(body);
				if (body == "") {
					console.log("Could not find a pricelist m8");
					return;
				}
				
				fs.writeFile("C:/Users/ahmad/Desktop/Bots/SteamKeyProfitter/gamespricelist/"+appid+".json", body, function(err) {
					if(err) {
						console.log("Error saving data to game pricelist: " + err);
						return;
					}
					console.log("Game pricelist has been updated!");
				});
			});
		}
	}
}

我有一个json文件,这个json文件叫做gamekeys.json

这里是:

{
    "keys": [
            {
                "appid": 10,
                "price":0, 
                "listofkeys":[], 
                "game": "Counter-Strike"
            },
            {
                "appid": 20,
                "price":0, 
                "listofkeys":[], 
                "game": "Team Fortress Classic"
            },
            {
                "appid": 30,
                "price":0, 
                "listofkeys":[], 
                "game": "Day of Defeat"
            },
            {
                "appid": 40,
                "price":0, 
                "listofkeys":[], 
                "game": "Deathmatch Classic"
            },

它当然会继续运行(200 万行)

为什么第一个代码没有创建95个json文件?

【问题讨论】:

    标签: javascript arrays json node.js api


    【解决方案1】:

    问题是您的appid 对于所有writeFile 调用都是相同的。

    尝试改变:

    appid = gamekeys.keys[i].appid;
    

    到:

    let appid = gamekeys.keys[i].appid;
    

    您需要为所有回调重新绑定,否则它们都将获得相同的值(来自上一次循环迭代)。请注意var 在这里不起作用,您需要let。如果您在其中一个闭包中使用i,那么您还需要使用for (let i = ...) 而不是for (var i = ...)

    apiurl 可以用var 声明,因为它的值被传递给request() 调用而不是被闭包捕获,但是如果你使用let 并且永远不要使用var 你不用担心。

    如果您总是以'use strict';(带引号)开始每个程序,并且从不使用var(改为使用letconst),那么您在此处的作用域就不会有问题,所以它是使用 linter 遵循和执行的良好做法。

    这是问题之一。可能还有更多,但这肯定是其中之一。

    更新

    回答 Alex 的评论“为什么他不能使用 var appid”

    运行此代码:

    for (var i = 0; i < 4; i++) {
      let appid = 'ID' + i;
      setTimeout(function () {
        console.log(appid);
      }, 500 * i);
    }
    

    然后运行这个程序:

    for (var i = 0; i < 4; i++) {
      var appid = 'ID' + i;
      setTimeout(function () {
        console.log(appid);
      }, 500 * i);
    }
    

    并比较输出。

    这说明了letvar 之间的区别。

    有关letvar 之间区别的更多信息,请参阅此答案:

    【讨论】:

    • 为什么他不能使用var appid,它目前不起作用的唯一原因是appid 被提升到全局范围,因为他没有var 声明。我认为let 无论如何都会转换为var,而let 仅适用于启用strict 模式以不允许重新定义常量。
    • @Alex 如果您不想重新定义常量,则不要使用 let,而是使用 constletvar 之间的区别是块作用域与函数作用域。有关示例,请参阅我的更新答案,并参阅 this answer 了解更多详细信息以及实际上 let 被转换为的解释。
    • 这是有道理的,所以因为在该块中有一个 setTimeout,我们使用 leti 绑定到当前循环迭代的上下文,因为 500 毫秒后 i 是 @987654362 @ 因为循环已完成执行,但在事件队列中安排了 4 个要处理的任务,其中 i 在该词法范围内是 3。 Gotcha,我以前从未真正考虑过这一点,知道真的很有用。干杯:)
    猜你喜欢
    • 2011-04-08
    • 2017-04-11
    • 1970-01-01
    • 2020-04-18
    • 1970-01-01
    • 2017-11-15
    • 2022-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多