【问题标题】:Can't pass global variables inside a function不能在函数内部传递全局变量
【发布时间】:2017-07-08 17:46:14
【问题描述】:

我正在尝试使用需要在另一个函数中重新运行的变量运行 FOR 循环,我需要将它们从第一个函数中编码出来, 但是函数将它们接收为“未定义”。

当变量在 collectionChecking 函数中是本地的,除了 ledTypes2 时,当handleResponse2 的函数试图调用他时,hostIndx2 的变量是未定义的。此函数应将响应呈现为 HTML 页面内 ledTypes2 方法的图标。

var fetch = require('node-fetch');

var ledTypes = {
    green: "<img id='logo' src='green.png' height='30' width='30'>",
    red: "<img id='logo' src='red.png' height='30' width='30'>",
    yellow: "<img id='logo' src='yellow.png' height='30' width='30'>"
};

var hosts2 = ['http://host1.com','host2.com','host3.com','host4.com'];
var hostIndx2 = 0;

var lengthVal = hosts2.length;
var token = '1213232431';
    function collectionChecking() {

        console.log("im inside the func" + hostIndx2 + "---" + lengthVal);
        for (; hostIndx2 < lengthVal; hostIndx2++) {
            console.log(hostIndx2);
            let url = hosts2[hostIndx2];
            // sendReq();
            fetch(url , {method: 'GET', headers:{"X-AUTH-TOKEN": token, "Content-Type": "text/plain"}, timeout: 30000}
            ).then(function (res, hostIndx2) {
                    console.log(res.status, hostIndx2);
                    handleLedResponse2(res, hostIndx2);

                });
        }
    }

function handleLedResponse2(res, hostIndx2) {
    var curSpan = document.getElementById('col_host_' + hostIndx2);
    console.log("IM HERE" + res.status + "---" + hostIndx2);
    if (res.status === 200 || res.status === 204) {
        curSpan.innerHTML = ledTypes.green;
    } else if (res.status === 500 || res.status === 404) {
        curSpan.innerHTML = ledTypes.red;
    } else if (res.status === 300 || res.status === 301 || res.status === 302) {
        curSpan.innerHTML = ledTypes.yellow;
    }
}

【问题讨论】:

  • 请更具体地说明您遇到的问题。哪些确切的变量是未定义的,在哪一行代码上?而且,“需要将它们从第一个函数中编码出来”是什么意思?请更具体地说明您遇到的问题以及您想要实现的目标。
  • 谢谢,handleResponse2 的函数试图调用他时,hostIndx2 的变量未定义。此函数应将响应呈现为 HTML 页面内 ledTypes2 方法的图标。

标签: javascript node.js rest loops variables


【解决方案1】:

这段代码有多个错误。

对于初学者,您不能在异步响应中使用像这样的for 循环索引变量。 for 循环将在调用 handleLedResponse2() 之前完全完成,因此它不会具有所需的值。

其次,您要声明一个 .then() 处理程序,以便在此行上有两个参数:

.then(function (res, hostIndx2) {

按照规范,.then() 处理程序仅传递一个参数。因此,您定义了一个名为 hostIndx2 的参数,该参数始终为 undefined,它将“隐藏”同名的更高范围变量,因此您无法访问它。
这就是为什么您看到的值总是undefined。首先要修复的是把上面的代码改成这样:

.then(function (res) {

这将使您能够访问更高范围的hostIndx2 变量(它将不再是undefine)。但是,由于同步 for 循环和异步 fetch() 调用的混合,它可能不会具有所需的值,因为 for 循环将在任何 fetch().then() 处理程序被调用之前运行完成。

我认为这解释了这部分代码有什么问题,但我不能完全推荐完整的修复,因为我不确定你要做什么。我认为hostIndx2 根本不应该是一个更高范围的变量,因为这只会导致问题并为其他事物提供机会来击败它。它应该是一个局部变量,然后你应该将它作为参数传递给你想要访问它的任何东西。

要解决异步访问它的问题,有多种选择。您可以使用let 切换到在for 循环本身中定义它,并且循环的每次调用都将获得它自己单独的变量版本(解决异步访问问题)。或者,您可以将循环更改为使用 forEach,这将为循环的每次调用创建一个新的唯一范围。


对你想要做的事情有一些猜测,这是一个清理后的版本:

const fetch = require('node-fetch');

const ledTypes = {
    green: "<img id='logo' src='green.png' height='30' width='30'>",
    red: "<img id='logo' src='red.png' height='30' width='30'>",
    yellow: "<img id='logo' src='yellow.png' height='30' width='30'>"
};

const hosts2 = ['http://host1.com','http://host2.com','http://host3.com','http://host4.com'];
const token = '1213232431';

function collectionChecking() {
    hosts2.forEach(function(url, index) {
        console.log("im inside the func" + index);
        fetch(url , {method: 'GET', headers:{"X-AUTH-TOKEN": token, "Content-Type": "text/plain"}, timeout: 30000}).then(function (res) {
            console.log(res.status, index);
            handleLedResponse2(res, index);
        });
    }
}

function handleLedResponse2(res, hostIndx2) {
    let curSpan = document.getElementById('col_host_' + hostIndx2);
    console.log("IM HERE" + res.status + "---" + hostIndx2);
    if (res.status === 200 || res.status === 204) {
        curSpan.innerHTML = ledTypes.green;
    } else if (res.status === 500 || res.status === 404) {
        curSpan.innerHTML = ledTypes.red;
    } else if (res.status === 300 || res.status === 301 || res.status === 302) {
        curSpan.innerHTML = ledTypes.yellow;
    }
}

附:我在这里有点困惑,因为您的问题被标记为 node.js 并且您似乎正在使用 node-fetch (这意味着 node.js 环境),但随后您显示 document.getElementById() 这不是您可以使用的在 node.js 中 - 这通常是可以在浏览器中运行的代码。

【讨论】:

  • 谢谢,我会尝试您的解决方案并让您知道结果。这是我第一次处理这个用例,我遇到了很多问题。这段代码的合理性是向多个主机发送 GET 请求,并在 HTML 页面中的分隔跨度标签中呈现它们的响应,类似于仪表板。但这是一个跨域请求,所以我使用的是 fetch 函数而不是 XMLhttp 处理程序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多