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

时间:2020-07-16 14:08:29

标签: javascript typescript asynchronous jestjs supertest

我正在结合使用Jest和Supertest来测试API端点。我使用Jest的beforeAll()函数在进行一系列测试之前调用一次端点。在调用端点之前,我正在使用fs.readFile从文件读取请求正文。

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

代码:

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本身是一个异步函数这一事实有关?

2 个答案:

答案 0 :(得分:4)

尝试await fs.promises.readFile('file.txt')代替?

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

答案 1 :(得分:1)

async functions隐式将其返回值转换为Promise。因此,您的函数签名async function readRequestBody() : Promise<string>意味着readRequestBody将返回一个Promise来创建Promise来读取正文。即Promise<Promise<String>>。相反,您需要从返回值中删除async关键字或Promise

该函数的实现也不正确,因为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)
      });      
    });
}