代码之家  ›  专栏  ›  技术社区  ›  gib65

为什么当一切都是同步的时,我的API调用不返回?

  •  0
  • gib65  · 技术社区  · 6 年前

    我在前端有一个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');
    }
    

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

    现在让我们看看修复:

    前端:

    等待api.post(`blahBlahEndpoint`);
    }捕捉(错误){
    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');
    }
    

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

    1) 如果没有async/await模式(bug存在的地方),那么从RequestHandler到DAO的所有方法调用只在方法完成时返回,而它们不返回任何内容(除了RequestHandler将状态为204的HttpResponse返回到前端)。

    3) 由于DAO.setSomething(…)没有等待对runQuery的调用,因此它在完成对runQuery的调用后立即执行。从runQuery返回的承诺将被删除。当runQuery执行其任务(更新DB)时,API开始其往返过程的返回部分,不返回任何内容。

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

    ^4)似乎没有发生的事情。所有的后端日志都表明,一切都像我上面描述的那样工作,直到返回HttpResponse为止,对数据库的更新证实了这一点。这告诉我上面的代码(pre-fix)对后端返回前端的方式有什么影响,但具体是什么?

    下面是我想象中的修复过程:

    2) 在RequestHandler中,对controller中setSomething(…)的调用是异步进行的,这意味着它立即返回一个promise并等待。

    3) 在控制器的setSomething(…)中,调用DAO.setSomething(…)。因为这是异步的,所以它会立即返回一个承诺并等待。

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

    5) 一旦从runQuery(…)返回的承诺被解析(因为runQuery(…)完成),DAO.setSomething(…)返回。

    6) 从DAO.setSomething(…)返回的承诺由DAO.setSomething(…)返回来解决,它停止等待。这将导致Controller.setSomething(…)返回。

    7) Controller.setSomething(…)返回的承诺由Controller.setSomething(…)返回解析,RequestHandler停止等待。

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

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

    0 回复  |  直到 6 年前