【问题标题】:Read File Asynchronously in Node.js在 Node.js 中异步读取文件
【发布时间】:2020-12-02 19:04:38
【问题描述】:

对于我的班级,我的教授希望我们创建一个简单的 node.js 网站,该网站读取包含完全限定 URL 的文本文件,然后使用该 URL 从远程网站检索 JSON 数据并最终保存 检索到的 JSON 到另一个文本文件。他希望将 URL 存储在全局变量中。

我已经用硬编码的 URL 完成了这项工作,该 URL 应该是从文件中读取的。运行良好,可以满足我的要求。我的问题是当我尝试为 URL 创建全局变量时,它总是返回未定义。我知道这是一个时间问题,因为文件没有被异步读取,但我不知道如何解决它。

'use strict';
// load the built-in http module
let http = require('http');
// load the add-in express module
let express = require("express");
// load the add-in xmlhttprequest and create XMLHttpRequest object
let XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
// create app object from express() constructor
let app = express();
// create a port number
let port = process.env.PORT || 3000;
let fs = require('fs');

// create a "get" event handler function
// request and response object references (req, res)
function getJSON() {
    app.get("/", function (reqNode, resNode) {
        var test = new Promise(function (resolve, reject) {
            var req = new XMLHttpRequest();
            req.open('GET', 'http://gd2.mlb.com/components/game/mlb/year_2017/month_07/day_08/master_scoreboard.json');
            req.onload = function () {
                if (req.status === 200) {
                    resolve(req.responseText);
                }
                else {
                    reject(req.statusText);
                }
            }
            req.onerror = function () {
                reject("network error");
            };

            req.send();
        });

        test.then(
            function (response) {
                // display in browser on success
                resNode.send('JSON data saved to file.');
            },
            function (error) {
                console.error("Request failed: ", error);
            }
        ),
            test.then(
                function (response) {
                    // write the response to json.txt
                    fs.writeFile('json.txt', response, function (err) {
                        if (err) {
                            console.log(err);
                        }
                        else {
                            console.log('JSON data saved to file.');
                        }
                    });
                },
                function (error) {
                    console.log(error);
                }
            ),
            test.catch(
                error => console.log(error)
            )
    });
}

(function () {
    // create a server object
    let server = http.createServer(app);

    // listen on specified port for get requests
    server.listen(port);
    // call getJSON function
    getJSON();
})();

此代码适用于硬编码的 URL,但我需要一个函数将其存储在全局变量中。

依赖关系:

"dependencies": {
    "express": "^4.17.1",
    "xmlhttprequest": "^1.8.0"
  }

而且,我尝试过的异步/等待。 'url' 变量返回未定义,所以这不起作用。没有返回错误,但是 localhost 加载失败。

'use strict';
// load the built-in http module
let http = require('http');
// load the add-in express module
let express = require("express");
// load the add-in xmlhttprequest and create XMLHttpRequest object
let XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
// create app object from express() constructor
let app = express();
// create a port number
let port = process.env.PORT || 3000;
let fs = require('fs');

function readTxt() {
    fs.readFile('urls.txt', { encoding: 'utf-8' }, function (err, data) {
        if (err) {
            console.log('Error reading file: ' + err)
        }
        else {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    resolve(data);
                }, 3000)
            });
        }
    });
}


// create a "get" event handler function
// request and response object references (req, res)
async function getJSON() {
    let url = await readTxt();
    console.log(url);
    app.get("/", function (reqNode, resNode) {
        var test = new Promise(function (resolve, reject) {
            var req = new XMLHttpRequest();
            req.open('GET', url);
            req.onload = function () {
                if (req.status === 200) {
                    resolve(req.responseText);
                }
                else {
                    reject(req.statusText);
                }
            };

            req.onerror = function () {
                reject("network error");
            };

            req.send();
        });

        test.then(
            function (response) {
                // display in browser on success
                resNode.send('JSON data saved to file.');
            },
            function (error) {
                console.error("Request failed: ", error);
            }
        ),
            test.then(
                function (response) {
                    // write the response to json.txt
                    fs.writeFile('json.txt', response, function (err) {
                        if (err) {
                            console.log(err);
                        }
                        else {
                            console.log('JSON data saved to file.');
                        }
                    });
                },
                function (error) {
                    console.log(error);
                }
            ),
            test.catch(
                error => console.log(error)
            )
    });
}

(async function () {
    // create a server object
    let server = http.createServer(app);

    // listen on specified port for get requests
    server.listen(port);
    // call getJSON function
    getJSON();
})();

我不相信这是重复的。我查看了其他问题,我尝试使用 async/await(上面的代码),作为对这个问题的回答:https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call. 这可能会起作用,但我无法正确设置它。提前致谢!

【问题讨论】:

  • 您应该提供失败的代码、失败的证明(例如您在控制台中遇到的错误)以及您对代码的期望。
  • 我会这样做的。谢谢。

标签: javascript node.js ajax asynchronous


【解决方案1】:

您对readTxt 函数的实现是错误的。这是它的正确实现。我添加了 cmets 来描述如何使用 Promise。

function readTxt() {
    // return a promise from the function
    return new Promise(function (resolve, reject) {
      // do the asynchronous operation
      fs.readFile('urls.txt', { encoding: 'utf-8' }, function (err, data) {
        if (err) {
            console.log('Error reading file: ' + err)
            // reject the promise in case of error
            reject(err);
        }
        else {
            setTimeout(function () {
                // resolve the promise after successfull execution of asynchronous code
                resolve(data);
            }, 3000)
        }
    });
}

【讨论】:

  • 好的,我认为这可行,然后意识到,我从未删除硬编码的 URL。运行时,URL 被正确读取(可以从控制台看出),但现在我收到 error404 说“GET localhost:3000404 (Not Found)”。
  • 看起来这里的 url 是“localhost:3000”或者undefined 所以这取决于你想要的 url。但这将是另一个问题。鼓励有关 stackoverflow 的问题具体化,以便更容易回答并为未来的读者提供价值。
  • 你应该删除这条评论,因为它不是正确的答案。在使用您提供的代码之前,我没有遇到任何问题。
  • 好吧,回答我自己的问题,只需将主机定义为 '127.0.0.1' 并将其添加到 server.listen 参数中。然后它起作用了。
  • 您的问题是关于您无法异步读取文件。正如您所提到的,答案中提供的代码允许读取文件。那怎么不是正确答案呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-23
  • 2018-11-13
  • 2015-01-30
  • 2015-01-25
  • 2018-04-29
  • 1970-01-01
  • 2016-03-17
相关资源
最近更新 更多