这段代码可能出了什么问题?在forEach循环之后,我无法获得更新的json(变量更新DataJSON)输出,任何人都可以帮助我吗?提前感谢,这是我的代码,我在这里错过了什么吗?
app.get('/getDifferences', (req, res) => {
let changed = false,
updatedJSON = { data: [] },
updatedDataJSON = { "url": "", "dta": "", "status": "unchanged" };
fs.readFile('output.json', 'utf-8', (err, data) => {
storedData = data && JSON.parse(data);
if (storedData) {
storedData.data.forEach((e) => {
request.get(e.url).on('res', (html) => {
updatedDataJSON.url = e.url;
updatedDataJSON.dta = e.dta;
if (e.dta && (e.dta.match(/<body[^>]*>[sS]*</body>/gi)[0] !== html.match(/<body[^>]*>[sS]*</body>/gi)[0])) {
changed = true;
updatedDataJSON.status = "changed";
updatedDataJSON.dta = html;
}
updatedJSON.data.push(updatedDataJSON);
});
});
console.log(updatedDataJSON);
}
});
res.end(JSON.stringify(updatedJSON))
});
Node js 是异步的。因此,您必须在forEach循环中结束get请求的回调中的响应,当get请求将调用存储Data.data长度时间时。
在这里,我附上代码来演示这一点。
app.get('/getDifferences', (req, res) => {
let changed = false,
updatedJSON = { data: [] },
updatedDataJSON = { "url": "", "dta": "", "status": "unchanged" };
fs.readFile('output.json', 'utf-8', (err, data) => {
var count = 0,
arraylength;
storedData = data && JSON.parse(data);
if (storedData) {
arraylength = storedData.data;
storedData.data.forEach((e) => {
request.get(e.url).on('res', (html) => {
updatedDataJSON.url = e.url;
updatedDataJSON.dta = e.dta;
if (e.dta && (e.dta.match(/<body[^>]*>[sS]*</body>/gi)[0] !== html.match(/<body[^>]*>[sS]*</body>/gi)[0])) {
changed = true;
updatedDataJSON.status = "changed";
updatedDataJSON.dta = html;
}
updatedJSON.data.push(updatedDataJSON);
count++;
if (count === arraylength) {
console.log(updatedDataJSON);
res.end(JSON.stringify(updatedJSON));
}
});
});
}
});
});
问题
他代码的执行顺序与编写它的顺序不同。这称为异步。这意味着request.get被解雇,然后解决。
你希望这个。
- 读取文件。
- 完成第一项。
- 请求第一项的数据(它被触发)
- 接收第一项的数据(它解析)
- 完成第二项。
- 请求第二项的数据(它被触发)
- 接收第二项的数据。(它解决)
正在发生的事情更像是这样的:
- 读取文件。
- 完成第一项。
- 请求第一项的数据(它被触发)
- 完成第二项。
- 接收第一项的数据(它解析)
- 请求第二项的数据(它被触发)
看看顺序有何不同?代码先转到第二项,然后再从第一项接收数据。这是因为您正在向网络服务器询问一些数据。同时,您的代码继续运行,然后网络服务器说"嘿,这是您要求的数据"。
想象一下,摆好桌子,你把叉子放在桌子上,让我把刀拿来。放一把叉子,等我带一把刀。你再放一把叉子,等我拿刀等等。
或
你向我要刀,同时把所有的叉子都放在桌子上,不要等我。当我拿着刀来时,你把它们放在桌子上。
解决方案1)签出异步/等待: https://tutorialzine.com/2017/07/javascript-async-await-explained
或
2)减少承诺:https://gist.github.com/anvk/5602ec398e4fdc521e2bf9940fd90f84
除了https://www.youtube.com/watch?v=8aGhZQkoFbQ
节点.js 是异步的,它在读取文件之前返回响应。 尝试异步模块或承诺处理异步操作。