首页 > 解决方案 > 当一切都同步时,为什么我的 API 调用不返回?

问题描述

我在前端有一个 Vue.js 应用程序,在后端有一个 Node.js REST API(在 AWS 上)。

我正在从前端调用后端并收到 504 错误(网关超时),但我不知道为什么。然后我从应用程序的其他地方几乎相同的模式复制了代码,它工作了。我不知道为什么它起作用了。我希望有人可以向我解释为什么我的代码不起作用以及为什么我复制的代码起作用。

首先你需要知道我的代码是什么样的。所以这里是:

前端:

     async saveTimestamp() {
       try {
         await api.post(`blahBlahEndpoint`);
         this.flag = false;
       } catch (err) {
         console.log('err=', err);
       }
     }

后端:

请求处理程序:

require('./blahBlahController').setSomething(params);
return new HttpResponse(204);

控制器:

setSomething(params) {
  this.dao.setSomething(params);
}

道:

setSomething(params) {
  this.db.runQuery('blah blah query with params');
}

所以本质上,前端向后端发送一个发布请求。端点是我们的 RequestHandler,一旦它为工作找出正确的控制器和方法,它就需要控制器并调用该方法,并将请求附带的任何参数传递给它。控制器依次调用 DAO 上的方法并传递参数。DAO 上的方法 (setSomething(...)) 将参数注入到传递给 db.runQuery(...) 的查询字符串中。db.runQuery 来自第三方库。它本质上是针对我们的数据库运行查询(在我的例子中,做一个简单的字段更新)。它是异步的,因此返回一个承诺。如您所见,我忽略了承诺并立即返回(我不需要查询的结果,所以我只是让它做它的事情并继续)。所以除了 runQuery(... ),一切都是同步的。那为什么我的前端调用超时?大约一分钟的等待后,catch 块捕获了一个 504 错误,谷歌告诉我这是一个超时错误。

现在让我们看看修复:

前端:

     async saveTimestamp() {
       try {
         await api.post(`blahBlahEndpoint`);
         this.flag = false;
       } catch (err) {
         console.log('err=', err);
       }
     }

后端:

请求处理程序:

await require('./blahBlahController').setSomething(params);
return new HttpResponse(204);

控制器:

async setSomething(params) {
  await this.dao.setSomething(params);
}

道:

async setSomething(params) {
  await this.db.runQuery('blah blah query with params');
}

很简单。我只是将后端的所有内容都转换为 async/await。但是为什么这可以解决问题。我显然不了解异步/等待模式如何处理承诺和/或如何改变前端和后端之间的动态(至少使用 REST API)。

以下是我所做的一些假设,可能是错误的:

1) 如果没有 async/await 模式(存在错误),从 RequestHandler 到 DAO 的所有方法调用仅在方法完成时返回,并且它们不返回任何内容(RequestHandler 除外,它返回带有 204 的 HttpResponse状态到前端)。

2) 因为runQuery 是异步的,所以它返回一个promise,并且它立即返回它(即在它完成之前)。

3) 由于 DAO.setSomething(...) 不等待对 runQuery 的调用,它在调用 runQuery 后立即继续。从 runQuery 返回的承诺被丢弃。当 runQuery 做它的事情(更新数据库)时,API 开始其往返的返回部分,什么都不返回。

4)RequestHandler最终返回一个HttpResponse对象给前端。在前端,这个对象成为被等待的 Promise 的对象,有效地解决了 Promise 并允许 API 调用停止等待。

^ 4) 似乎没有发生。所有后端日志都表明一切正常,就像我上面描述的那样,直到返回 HttpResponse,并且对数据库的更新证实了这一点。这告诉我上面的代码(预修复)如何影响后端返回前端的方式存在问题,但究竟是什么?

这是我想象的修复过程中发生的事情:

1)前端没有变化。前端像以前一样调用后端。

2) 在 RequestHandler 中,对控制器中的 setSomething(...) 的调用是异步进行的,这意味着它会立即返回一个 Promise 并等待。

3) 在 Controller 的 setSomething(...) 中,调用 DAO.setSomething(...)。由于这是异步的,它会立即返回一个 Promise 并等待。

4) 在 DAO.setSomething(...) 中,调用 runQuery(...)。由于 runQuery(...) 是异步的,它会立即返回一个 Promise 并等待。

5) 一旦从 runQuery(...) 返回的承诺得到解决(因为 runQuery(...) 完成),DAO.setSomething(...) 返回。

6) DAO.setSomething(...) 返回的 promise 由 DAO.setSomething(...) 返回解决,并停止等待。这会导致 Controller.setSomething(...) 返回。

7)Controller.setSomething(...)返回的promise由Controller.setSomething(...)返回解决,RequestHandler停止等待。

8) RequestHandler 将 HttpResponse 对象返回给前端,状态为 204。

9) api调用返回的promise是通过返回的HttpResponse对象来解决的。承诺解析为 HttpResponse 对象。前端停止等待并继续。

^ 希望这能详细说明我对前端请求和后端响应的理解,以及涉及承诺和异步/等待模式时会发生什么。有人愿意纠正我的任何误解吗?有什么可以解释为什么前端在修复前状态下没有得到响应?

非常感谢任何即将到来的回复。

标签: restpromiseasync-awaitfrontendbackend

解决方案


推荐阅读