Почему мой вызов API не возвращается, когда все происходит синхронно? - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть приложение Vue. js на внешнем интерфейсе и Node.js REST API на внутреннем сервере (на AWS).

Я звонил на внутренний сервер из передний конец и получение ошибки 504 (время ожидания шлюза), и я не мог понять, почему. Затем я скопировал код из почти идентичного шаблона в другом месте приложения, и это сработало. Я не знаю, почему это сработало. Я надеюсь, что кто-то может объяснить мне, почему мой код не работает и почему код, который я скопировал, работает.

Сначала вы должны знать, как выглядит мой код. Итак, вот оно:

FRONTEND:

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

BACKEND:

RequestHandler:

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

Контроллер:

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

DAO:

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

Итак, по сути, внешний интерфейс отправляет запрос на отправку серверу. Конечной точкой является наш RequestHandler, и, как только он определяет правильный контроллер и метод для работы, он требует контроллера и вызывает метод, передавая ему любые параметры, которые пришли с запросом. Контроллер в свою очередь вызывает метод в DAO, передавая параметры вместе. Метод в DAO (setSomething (...)) вставляет параметры в строку запроса, которая передается в db.runQuery (...). db.runQuery из сторонней библиотеки. По сути, он выполняет запрос к нашей базе данных (в моем случае это простое обновление поля). Это асинхронный и, следовательно, возвращает обещание. Как видите, я игнорирую обещание и просто сразу возвращаюсь (мне не нужны результаты запроса, поэтому я просто позволил ему выполнить свою задачу и продолжить). Так что, кроме runQuery (...), все синхронно. Почему тогда тайм-аут моего внешнего интерфейса? Примерно через минуту ожидания блок catch обнаруживает ошибку 504, которая, по словам Google, является ошибкой тайм-аута.

Теперь давайте посмотрим на исправление:

FRONTEND:

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

BACKEND:

RequestHandler:

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

Контроллер:

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

DAO:

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

Очень просто. Я просто конвертировал все на сервере в async / await. Но почему это решает проблему. Я явно не понимаю, как шаблон async / await обрабатывает обещания и / или как это изменяет динамические параметры c между внешним интерфейсом и внутренним интерфейсом (по крайней мере, с помощью API REST).

Вот некоторые предположения, которые я делаю это может быть ложным:

1) Без шаблона async / await (где существовала ошибка) все вызовы метода из RequestHandler в DAO возвращаются только после завершения метода и ничего не возвращают (с исключение RequestHandler, который возвращает HttpResponse со статусом 204 во внешний интерфейс).

2) Поскольку runQuery асинхронный, он возвращает обещание и возвращает его немедленно (т.е. до того, как это будет сделано).

3) Поскольку DAO.setSomething (...) не ожидает вызова runQuery, он продолжается, как только завершится вызов runQuery. Обещание, возвращенное из runQuery, отбрасывается. В то время как runQuery делает свое дело (обновляет БД), API начинает возвращаемую часть своего обхода, ничего не возвращая.

4) RequestHandler наконец возвращает объект HttpResponse во внешний интерфейс. На внешнем интерфейсе этот объект становится объектом ожидаемого Обещания, эффективно решая обещание и позволяя вызову API прекратить ожидание.

^ 4), похоже, не происходит. Все журналы бэкэнда показывают, что все работает так же, как я описал выше, вплоть до момента возврата HttpResponse, и обновления базы данных подтверждают это. Это говорит мне о том, что есть проблема с тем, как мой код выше (предварительное исправление) влияет на то, каким образом сервер возвращается к внешнему интерфейсу, но что именно?

Вот что, я думаю, происходит с исправлением:

1) Нет изменений во внешнем интерфейсе. Frontend выполняет вызов для backend, как и раньше.

2) В RequestHandler вызов setSomething (...) в контроллере выполняется асинхронно, что означает, что он сразу же возвращает обещание и ожидается.

3) В наборе контроллера (). ..), вызов DAO.setSomething (...) сделан. Поскольку это асинхронно, оно сразу же возвращает обещание и ожидается.

4) В DAO.setSomething (...) выполняется вызов runQuery (...). Поскольку runQuery (...) является асинхронным, он сразу же возвращает обещание и ожидается.

5) Как только обещание, возвращенное из runQuery (...), будет разрешено (потому что runQuery (...) завершится ), Возвращается DAO.setSomething (...).

6) Обещание, возвращаемое из DAO.setSomething (...), разрешается возвратом DAO.setSomething (...) и перестает ожидать. Это приводит к возврату Controller.setSomething (...).

7) Обещание, возвращаемое из Controller.setSomething (...), разрешается возвращением Controller.setSomething (...), и RequestHandler перестает ожидать .

8) RequestHandler возвращает объект HttpResponse во внешний интерфейс со статусом 204.

9) Обещание, возвращаемое из вызова API, разрешается с помощью возвращаемого объекта HttpResponse. Обещание преобразуется в объект HttpResponse. Интерфейс перестает ждать и продолжается.

^ Надеюсь, это дает подробный отчет о том, что я понимаю, о запросах внешнего интерфейса и ответах бэкэнда, а также о том, что происходит, когда задействованы обещания и шаблоны асинхронности / ожидания. Кто-нибудь хочет исправить мои недоразумения? Что-нибудь, что могло бы объяснить, почему веб-интерфейс не получил ответ в состоянии перед исправлением?

Большое спасибо за любые ожидаемые ответы.

...