在nodejs/express 中,如何防止 if 条件在 readdir 完成之前执行?

发布于 2025-01-14 10:10:46 字数 860 浏览 1 评论 0原文

app.get('/students/:record_id', function (req, res) {
  var found =false;
  var record_id = req.params.record_id;
  var dirname = "students/";


  filenames = fs.readdirSync(dirname);
  filenames.forEach(filename => {
    
    fs.readFile(dirname + filename, "utf-8", function (err, data ) {
      if (err) {
        onError(err);
        return;
      }
      if (data.includes(record_id)) {
        found = true;
        return res.status(200).send(data);
        
      }
    });
  });

  if(found == false){ 
    return res.status(500).send({ "message": "error - no student found" });
  }

});

我正在使用 GET 按学生姓名搜索来检索学生文件。如果我删除 if 条件,则成功。但如果学生不存在,那么它就不起作用。 if 条件通过在文件中找到 find 时将其设为 true 来修复此问题。问题在于 if 条件在读取文件之前执行。 我尝试使用回调,但经过几个小时的研究,我无法弄清楚如何在其中实现它,因为 readfile 回调用于检索学生信息。

我尝试使用承诺,但只有找到学生时,承诺才会兑现,而我不知道如何在找不到学生时兑现承诺。

app.get('/students/:record_id', function (req, res) {
  var found =false;
  var record_id = req.params.record_id;
  var dirname = "students/";


  filenames = fs.readdirSync(dirname);
  filenames.forEach(filename => {
    
    fs.readFile(dirname + filename, "utf-8", function (err, data ) {
      if (err) {
        onError(err);
        return;
      }
      if (data.includes(record_id)) {
        found = true;
        return res.status(200).send(data);
        
      }
    });
  });

  if(found == false){ 
    return res.status(500).send({ "message": "error - no student found" });
  }

});

I am using GET searching by a student name to retrieve a students file. If I remove the if condition it is successful. But if the student does not exist then it does not work.
The if condition fixes this by making found true when it finds it in the file. The problem is that the if condition executes before the file is read.
I tried using a callback but after a couple hours of research I can not figure out how to implement it in this since the readfile callback is being used to retrieve student info.

I tried using a promise but the promise is then only fulfilled if the student is found and I do not know how to implement it where it is fulfilled when it is not found.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烈酒灼喉 2025-01-21 10:10:46

既然您已经尝试过使用 Promises,我将向您展示如何使用 Promises

使用 async/await 尤其使这变得非常简单

注意:因为我不知道您如何使用 fs 导入/require 只获取 readdir 和 readFile 的承诺版本,并像 readdir 而不是 fs.readdir 使用它 - 所以其他现有代码不会破坏

const {readFile, readdir} = require('fs/promises');

// if you use import (modules) instead of require (commonjs)
// import { readFile, readdir } from 'fs/promises';

app.get('/students/:record_id', async function (req, res) {
    var record_id = req.params.record_id;
    var dirname = "students/";

    try {
        const filenames = await readdir(dirname);
        for (let filename of filenames) {
            const data = await readFile(dirname + filename, "utf-8");
            if (data.includes(record_id)) {
                return res.status(200).send(data);
            }
        }
        res.status(404).send({"message": "error - student not found"});
    } catch (err) {
        onError(err);
        res.status(500).send({"message": "internal server error"});
    }
});

注意:我不会'发送 500 (内部服务器错误)如果找不到学生 - 我更改了逻辑以发送 404(未找到) - 这更合适

如果您想要纯粹的承诺(无异步/等待) - 我相信以下是一种方法它,可能不是最好的代码,但它应该可以工作(虽然还没有测试过)

const {readFile, readdir} = require('fs/promises');

// if you use import (modules) instead of require (commonjs)
// import { readFile, readdir } from 'fs/promises';

app.get('/students/:record_id', function (req, res) {
    var record_id = req.params.record_id;
    var dirname = "students/";
    
    let p = Promise.resolve(false);
    for (let filename of filenames) {
        p = p
        .then(found => 
            found ? found : readFile(dirname + filename, "utf-8")
            .then(
                data => 
                    data.includes(record_id) ? data : false
            )
        );
    }
    .then(data => data ? res.status(200).send(data) : res.status(404).send({"message": "error - student not found"}))
    .catch(err => {
        onError(err);
        res.status(500).send({"message": "internal server error"});
    })
});

并且,最后 - 根本不使用 Promises

app.get('/students/:record_id', function (req, res) {
    let found = false;
    const record_id = req.params.record_id;
    const dirname = "students/";

    const filenames = fs.readdirSync(dirname);
    const count = filenames.length;
    const checkFile = index => {
        if (index < count) {
            const filename = filenames[index];
            fs.readFile(dirname + filename, "utf-8", function (err, data) {
                if (err) {
                    onError(err);
                    res.status(500).send({"message": "internal server error"});
                } else if (data.includes(record_id)) {
                    res.status(200).send(data);
                } else {
                    checkFile(index + 1)
                }
            });
        } else {
            res.status(404).send({"message": "error - student not found"});
        }
    }
    checkFile(0);
});

Since you've tried with Promises, I'll show you how to do it with Promises

Using async/await especially makes this really easy

Note: since I don't know how you are using fs the import/require only gets the promise versions of readdir and readFile, and uses it like readdir rather than fs.readdir - so other existing code won't break

const {readFile, readdir} = require('fs/promises');

// if you use import (modules) instead of require (commonjs)
// import { readFile, readdir } from 'fs/promises';

app.get('/students/:record_id', async function (req, res) {
    var record_id = req.params.record_id;
    var dirname = "students/";

    try {
        const filenames = await readdir(dirname);
        for (let filename of filenames) {
            const data = await readFile(dirname + filename, "utf-8");
            if (data.includes(record_id)) {
                return res.status(200).send(data);
            }
        }
        res.status(404).send({"message": "error - student not found"});
    } catch (err) {
        onError(err);
        res.status(500).send({"message": "internal server error"});
    }
});

Note: I wouldn't send a 500 (Internal Server Error) if a student is not found - I changed the logic to send 404 (not Found) instead - which is more appropriate

If you want pure promise (no async/await) - I believe the following is one way to do it, probably not the nicest code, but it should work (haven't tested though)

const {readFile, readdir} = require('fs/promises');

// if you use import (modules) instead of require (commonjs)
// import { readFile, readdir } from 'fs/promises';

app.get('/students/:record_id', function (req, res) {
    var record_id = req.params.record_id;
    var dirname = "students/";
    
    let p = Promise.resolve(false);
    for (let filename of filenames) {
        p = p
        .then(found => 
            found ? found : readFile(dirname + filename, "utf-8")
            .then(
                data => 
                    data.includes(record_id) ? data : false
            )
        );
    }
    .then(data => data ? res.status(200).send(data) : res.status(404).send({"message": "error - student not found"}))
    .catch(err => {
        onError(err);
        res.status(500).send({"message": "internal server error"});
    })
});

And, finally - without using Promises at all

app.get('/students/:record_id', function (req, res) {
    let found = false;
    const record_id = req.params.record_id;
    const dirname = "students/";

    const filenames = fs.readdirSync(dirname);
    const count = filenames.length;
    const checkFile = index => {
        if (index < count) {
            const filename = filenames[index];
            fs.readFile(dirname + filename, "utf-8", function (err, data) {
                if (err) {
                    onError(err);
                    res.status(500).send({"message": "internal server error"});
                } else if (data.includes(record_id)) {
                    res.status(200).send(data);
                } else {
                    checkFile(index + 1)
                }
            });
        } else {
            res.status(404).send({"message": "error - student not found"});
        }
    }
    checkFile(0);
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文