Javascript / Node / Express: res.json нужно дождаться завершения функции, прежде чем вернуться ... но res.json нетерпелив? - PullRequest
3 голосов
/ 22 октября 2019

Привет друзья! Надеюсь, у вас все хорошо.

Итак, в этом фрагменте кода у меня есть список из десяти серверов, которые я хочу запросить. Эти десять серверов представлены десятью портами, которые я определил сверху в const "ports".

Идея состоит в том, чтобы использовать forEach () для "ports" и запускать запрос на каждом сервере. Объект возвращается при каждом запуске запроса и добавляется в изначально пустой массив «data».

ТО! После того, как «данные» были загружены с десятью объектами, содержащими статус моих серверов, я хочу вернуть их обратно на клиентскую сторону!

Однако ..... это не то, что происходит. Port.forEach () прекрасно выполняет запрос и добавляет в массив «данные» ... но не раньше, чем res.json бросает оружие и отправляет пустые данные обратно моему скоро разочаровавшемуся клиенту.

Пока ... Я пробовал обратные вызовы и async / await ... но я не определил синтаксис для него ... Любые советы будут потрясающими! Спасибо за ваше время, друзья!

module.exports = app => {
  app.get("/api/seMapServerStatus", (req, res) => {

  const ports = [ "27111", "27112", "27117", "27118", "27119", "27110", "27115", "27116", "27113", "27114" ]
  const data = []

    function hitServers(port){
        Gamedig.query({
          type: "aGameType",
          host: "theServer'sIP",
          port: port
        }).then((state) => {
          data.push(state)
          console.log("this is the server", state)
        }).catch((error) => {
          console.log("Server is offline");
        });  
    };

    ports.forEach(port => {
      hitServers(port)
    })
  });
  console.log("and here is the final server list", data)
  res.json(data);   
}

1 Ответ

2 голосов
/ 22 октября 2019

Приведенный выше код выполняется синхронно, поэтому вы возвращаетесь в том же кадре, прежде чем какое-либо обещание сможет решить.

Мы можем очистить приведенный выше код следующим образом:

module.exports = app => {

  app.get("/api/seMapServerStatus", (req, res) => {
    const ports = ["27111", "27112", "27117", "27118", "27119", "27110", "27115", "27116", "27113", "27114"]

    function hitServers(port) {
      return Gamedig.query({
        type: "aGameType",
        host: "theServer'sIP",
        port: port
      })
    }

    // With error handling
    function hitServersSafe(port) {
      return hitServers(port)
        .then(result => {
          return {
            success: true,
            result: result
          }
        })
        .catch(error => {
          return {
            success: false,
             // you probably need to serialize error
            error: error
          }
        })
    }

    const promises = ports.map(port => hitServers(port))
    // With error handling
    // const promises = ports.map(port => hitServersSafe(port))

    Promise
      .all(promises)
      .then(data => res.json(data))
      .catch(error => {
        // do something with error
      })
  })

}

Мы сопоставляем каждый порт с обещанием. После того, как у нас есть список X обещаний, мы ждем, пока все из них завершат.

Вызывающий Promise.all() возвращает массив разрешенных значений или отклоняется, когда любое обещание отклоняется.

Только после того, как все обещания будут выполнены, мы можем двигаться дальше и отправлять результат клиенту.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...