Объедините результат нескольких асинхронных вызовов в одно сообщение с protobuf.js - PullRequest
0 голосов
/ 02 декабря 2018

Использование Protobuf.js Мне нужно объединить результат нескольких асинхронных вызовов в одно сообщение и затем отправить его в качестве ответа.Порядок асинхронных вызовов не может быть установлен априори.Я создал пример сценария, который вызывает три гипотетических удаленных сервиса: один возвращает сообщение о погодных условиях, один - время, а другой - местоположение.

Потенциально порядок вызовов является случайным, или, опять же, не все три службы должны быть вызваны.Чтобы объединить результаты, я отслеживал последовательность вызовов, затем я ждал, когда все вызовы вернутся, я декодировал различные возвращаемые сообщения, а затем я перекомпоновал все в новый объект и затем приступил к его кодированию.

Мне кажется, это очень громоздкая процедура, которая увеличивает задержку этого типа операции.Есть ли у вас какие-либо предложения по упрощению процедуры и повышению ее эффективности?

Вот пример сценария:

const protobuf = require("protobufjs");

const proto = `
syntax = "proto3";

message Location {
    string city = 1;
    string zip = 2;
}

message Weather {
    string condition = 3;
    string temperature = 4;
}

message Time {
    string day = 5;
    string year = 6;
}

message AllMetadata {
    optional Location location = 7;
    optional Weather weather = 8;
    optional Time time = 9;
}`;

const root = protobuf.parse(proto, { keepCase: true }).root;
const locTmp = root.lookup("Location");
const weaTmp = root.lookup("Weather");
const timeTmp = root.lookup("Time");
const allTmp = root.lookup("AllMetadata");

const asyncCall = (tmp, msg, timeout) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      let ret = tmp.encode(msg).finish();
      resolve(ret);
    }, timeout);
  });
};

const test = async () => {
  let metaWorkers = [];
  let callOrder = [];
  let ret = {};

  const add = (name, tmp, fnc) => {
    metaWorkers.push(fnc);
    callOrder.push({ name, tmp });
  };

  add(
    "weather",
    weaTmp,
    asyncCall(weaTmp, { condition: "cloud", temperature: "20" }, 100)
  );
  add(
    "location",
    locTmp,
    asyncCall(locTmp, { city: "rome", zip: "00152" }, 150)
  );
  add(
    "time",
    timeTmp,
    asyncCall(timeTmp, { day: "sunday", year: "2019" }, 200)
  );

  let results = await Promise.all(metaWorkers);

  results.forEach((res, i) => {
    let { name, tmp } = callOrder[i];
    ret[name] = tmp.decode(res);
  });

  let enc = allTmp.encode(ret).finish();
  return enc;
};

test().then(data => console.log(allTmp.decode(data)));
...