【问题标题】:Evaluate javascript for Fetch request为 Fetch 请求评估 javascript
【发布时间】:2019-03-11 18:10:48
【问题描述】:

我在 Windows 上使用 node.js,并带有 express 模块来生成我想从服务器返回数据的 HTML处理函数getfiledata()(即我不想公开我的js或txt文件)。

我一直在尝试使用fetch()getfiledata() 返回值。

问题:我无法从getfiledata() 获取数据返回到fetch()


HTML

<!DOCTYPE html>
<html>

<script type="text/javascript">
function fetcher() {
  fetch('/compute', {method: "POST"})
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(JSON.stringify(myJson));
  });
}
</script>

<input type="button" value="Submit" onClick="fetcher()">

</body>
</html>

^^ 包含我的 fetch() 函数

服务器

var express = require("express");
var app     = express();
var compute = require("./compute")

app.post('/compute',compute.getfiledata);

compute.js

var fs = require('fs');

module.exports={
  getfiledata: function() {
    console.log("we got this far");
    fs.readFile("mytextfile.txt", function (err, data) {
        if (err) throw err;
        console.log("data: " + data);
        return data;
    })
  }
}

^^ 包含我的服务器端函数

注意:从 compute.js 控制台成功记录:

我们已经走到了这一步

数据:这是文本文件中的数据

但不从以下位置登录: HTML

中的console.log(JSON.stringify(myJson))

我怀疑这是因为我没有设定“承诺”,但我不确定,希望能得到一些关于下一步的指导。

【问题讨论】:

  • 这与fetch无关。查看express 文档以了解如何提供 JSON - 您实际上需要编写 HTTP 响应。是的,您不能在 readFile 回调中使用 return
  • 这个问题的一半(从getfiledata()返回结果)在这里详细介绍:How do I return the response from an asynchronous request
  • 谢谢你,@jfriend00。我认为暂时我会尝试按照下面的答案处理此同步。如果性能成为问题,我已经参考了您链接的页面,以便将来将我的代码更新为异步。
  • @Bergi,我现在可能会将我的代码转换为同步计算,并期待将来“编写 HTTP 响应”。谢谢。

标签: javascript html node.js promise fetch


【解决方案1】:

我想你正在路上。我建议做一些小改动,你就可以了。

我建议使用 fs.readFileSync,因为这是一个非常小的文件(我想!!),因此不会对性能造成重大影响。我们可以使用 fs.readFile,但是我们需要插入一个回调,在这种情况下,我认为同步执行所有这些操作就可以了。

总结变化:

  • 我们需要在计算上调用 getFileData(),因为它是一个函数。
  • 我们将使用 readFileSync 来读取您的文本文件(因为它很快)。
  • 我们将调用 res.json 将响应编码为 json。
  • 我们将使用 express 静态中间件来提供 index.html。

要对此进行测试,请确保所有文件都位于同一目录中。

点击下面的命令进行服务:

node server.js

然后去http://localhost/查看网页。

server.js

var express = require("express");
var compute = require("./compute");
var app     = express();

app.use(express.static("./"));

app.post('/compute', (req, res, next) => {
    var result = compute.getfiledata();
    res.status(200).json({ textData: result } );
});

app.listen(80);

compute.js

var fs = require('fs');

module.exports = {
    getfiledata: function() {
      console.log("we got this far");
      return fs.readFileSync("mytextfile.txt", "utf8");
    }
}

index.html

<!DOCTYPE html>
<html>

<script type="text/javascript">
function fetcher() {
  fetch('/compute', {method: "POST"})
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(JSON.stringify(myJson));
    document.getElementById("output").innerHTML = "<b>Result: </b>" + myJson.textData;
  });
}
</script>
<input type="button" value="Submit" onClick="fetcher()">
<br><br>
<div id="output">
</div>
</body>
</html>

mytextfile.txt

那么,对你来说,这无关紧要,因为没有好坏之分,但思想决定了它。

【讨论】:

  • 谢谢。该代码有效,我相信它现在会满足。我希望将来我将需要使用异步处理,因为该 txt 文件可能会增长,或者在将 txt 文件的内容返回给浏览器之前可能会对 txt 文件的内容进行 js 计算。保重!
  • 应该可以,我不希望看到低于 100kb 的问题,但它很容易异步!
  • 在服务器路由处理程序中推荐同步 I/O 是个坏主意。 OP 正在开发服务器。他们应该学习使用异步 I/O 的“正确”方式。
  • 我同意,但是如果我们为同步支付 1 毫秒的罚款。 io,我们还需要一段时间才能遇到任何重大问题。
【解决方案2】:

这里有几个问题。首先,不能直接从getfiledata()返回异步数据。有关该问题的完整描述,请参阅 How do I return the response from an asynchronous call?。您必须使用回调来传回异步结果(就像fs.readFile() 所做的那样),或者您可以返回一个满足异步值的承诺。

其次,Express 中的路由处理程序(例如app.post())必须使用res.send()res.write() 或类似的东西将响应发送回调用者。仅从路由处理程序返回一个值不会做任何事情。

第三,您已经看到了使用同步 I/O 的其他建议。请,请不要那样做。除了启动代码之外,您永远不应该在任何服务器上使用同步 I/O,因为它绝对会破坏您的服务器一次处理多个请求的能力。相反,同步 I/O 强制请求串行处理(整个服务器进程等待并且在操作系统从磁盘获取内容时什么都不做),而不是让服务器在等待磁盘时使用所有可用的 CPU 周期来处理其他请求输入输出。

牢记这些,您的解决方案非常简单。我建议使用 Promise,因为那是 Javascript 和 node.js 的未来。

你的compute.js:

const util = require('util');
const readFile = util.promisify(require('fs').readFile);

module.exports= {
  getfiledata: function() {
    return readFile("mytextfile.txt");
  }
}

还有,你的 server.js:

const express = require("express");
const compute = require("./compute");
const app     = express();

app.use(express.static("./"));

app.post('/compute', (req, res) => {
    compute.getfiledata().then(textData => {
        res.json({textData});
    }).catch(err => {
        console.log(err);
        res.sendStatus(500);
    });
});

app.listen(80);

在 node.js 版本 10 中,fs 模块内置了一个用于承诺的实验性 API,因此您甚至不必像我上面那样手动承诺它。或者,您可以使用多个 3rd 方库中的任何一个,这些库可以很容易地一次性承诺整个 fs 库,因此您拥有模块中所有功能的承诺版本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-08
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多