.then 在 promise 解决之前触发

Posted

技术标签:

【中文标题】.then 在 promise 解决之前触发【英文标题】:.then triggering before promise resolved 【发布时间】:2020-12-27 18:28:24 【问题描述】:

我正在使用 mocha 和 supertest 在 Node 中编写集成测试,并且必须在数据库中创建用户。我的问题是,有时用户会在测试完成后得到保存。 这是我的用户创建函数:

async function createUser() 
  const userParam = 
    username: "User",
    password: "123456789",
    firstName: "Max",
    lastName: "Mustermann",
    role: JSON.stringify(Role.User),
  ;
  const user = new User(userParam);

  user.hash = bcrypt.hashSync(userParam.password, 10);

  await user.save();
  console.log("User saved!");

这是测试:

it("respond with 403 forbidden, because a standard user cant delete other users", function (done) 
        createUser().then(
          login(userLoginData).then((responseBody) => 
            request(app)
              .delete("/users/0000000000006204aefc242c")
              .set(
                "Authorization",
                `Bearer $responseBody.body.accessToken`,
              )
              .expect(
                403,
                
                  Error: "Forbidden",
                  message:
                    "Forbidden for your rank, if its not your own account.",
                ,
                done,
              );
          ),
        );
      );

这是我从 mocha 得到的输出:

  DELETE /
          Successes
    Admin saved!
    User saved!
          ✓ respond with 200 ok, because admins are allowed to delete all users (431ms)
    User saved!
          ✓ respond with 200 ok, because he is allowed to delete himself (195ms)
          Errors
            1) respond with 403 forbidden, because a standard user cant delete other users
    User saved!

前两个测试正在完成,因为所需的帐户是在测试之前创建的,但最后一个测试(如上所示)失败。

这里是当前 github 分支中文件的链接: https://github.com/Knniff/loginbackend/blob/2fa/test/tests.js

我很高兴收到所有反馈,如果您有更好的方法来做这些准备工作,我想听听。

【问题讨论】:

then 不会过早触发回调 - 你没有传递回调函数! 所以我应该对 .save 使用 return 而不是 await 吗? 不,这完全没问题,您的 createUser 函数有效。不起作用的是测试中的 .then(login(userLoginData).then(…)),其中 login 调用应该放在函数表达式中。 【参考方案1】:

您的测试中的第 2 行有问题。您无需等待 promise 解决并在 createUser() 函数之后立即调用 login() 函数。您应该将login() 函数调用包装到箭头函数() => login(userLoginData) 中。 您可以对测试进行以下更改:

      it("respond with 403 forbidden, because a standard user cant delete other users", function (done) 
        createUser()
          .then(() => login(userLoginData))
          .then((responseBody) => 
            request(app)
              .delete("/users/0000000000006204aefc242c")
              .set(
                "Authorization",
                `Bearer $responseBody.body.accessToken`,
              )
              .expect(
                403,
                
                  Error: "Forbidden",
                  message:
                    "Forbidden for your rank, if its not your own account.",
                ,
                done,
              );
          );
      );

编辑:

另外,我建议在您的测试中使用 async/await:

it("respond with 403 forbidden, because a standard user cant delete other users", async function () 
  await createUser();
  const responseBody = await login(userLoginData);
  await request(app)
    .delete("/users/0000000000006204aefc242c")
    .set(
       "Authorization",
       `Bearer $responseBody.body.accessToken`,
    )
    .expect(
       403,
       
         Error: "Forbidden",
         message: "Forbidden for your rank, if its not your own account."
       
    );
 
);

【讨论】:

非常感谢,我之前尝试过异步等待路由,但尝试将它与完成混合,所以我无处可去。我现在可以完美地工作了。

以上是关于.then 在 promise 解决之前触发的主要内容,如果未能解决你的问题,请参考以下文章

Promise then() 方法没有按预期触发? [复制]

Promise 的三种状态,以及then、catch的链式调用

实现一个自定义Promise

实现一个自定义Promise

async await promise

最近在找前端工作,然后面试的时候人家问我。promise为啥能解决地狱回调,为啥能一直.then?