从另一个异步函数等待 fs.readFile 的正确方法是什么?

What is the correct way to await fs.readFile from another asynchronous function?

我正在使用 Jest 和 Supertest 的组合来测试 API 端点。我正在使用 Jest 的 beforeAll() 函数在一组测试之前调用端点一次。在调用端点之前,我正在使用 fs.readFile.

从文件中读取请求正文

无论我尝试什么,我似乎都无法等待调用 fs.readFile 的函数的结果。我的请求每次都会产生 400 响应,因为没有等待函数 readRequestBody。程序流程似乎在继续而不等待结果,因此发送了一个空的请求体。

代码:

describe("Test POST call " + process.env.ENV, () => {
    const url = config.apiURL;
    let responseData: request.Response;

    beforeAll(async (done) => {
        const requestBody = await readRequestBody();
        responseData = await request(config.apiURL)
            .post("/v1.0/subjects/courses")
            .send(requestBody)
            .accept("application/vnd.api+json")
            .set("content-type", "application/vnd.api+json");
        done();
    });

    test("authorized should return 201 status code", () => {
        expect(responseData.status).toBe(201);
    });
});

async function readRequestBody() : Promise<string> {
    let requestBody: string = "";

    fs.readFile("./request.json", "utf8", (err, req) => {
        if (err) {
            console.log("Error loading request: " + err.message)
        }
        requestBody = req.replace("{{newCourseUuid}}", uuid.v4());
    });

    return requestBody;
}

我知道 fs.readFile 异步读取文件的内容,但看起来我没有正确等待结果。我错过了什么?这是否与 beforeAll 本身是一个异步函数有关?

尝试 await fs.promises.readFile('file.txt') 而不是

https://nodejs.org/api/fs.html#fs_fs_promises_api

async functions 将它们的 return 值隐式转换为承诺。所以你的函数签名 async function readRequestBody() : Promise<string> 意味着 readRequestBody 将 return 一个 Promise 来创建 Promise 来读取主体。即 Promise<Promise<String>>。相反,您需要从 return 值中删除 async 关键字或 Promise

此外,您对该函数的实现也不正确,因为它总是 return 一个空字符串,因为 fs.readFile 是一个异步函数。

以下内容可能会解决您的两个问题:

function readRequestBody() : Promise<string> {
    return new Promise((resolve, reject) => {
      fs.readFile("./request.json", "utf8", (err, req) => {
          if (err) {
              console.log("Error loading request: " + err.message)
              reject(err)
          }
          let requestBody: string = "";
          requestBody = req.replace("{{newCourseUuid}}", uuid.v4());
          resolve(requestBody)
      });      
    });
}