Объедините результат нескольких асинхронных вызовов в одно сообщение с protobuf.js
Используя 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)));