У меня есть приложение nodejs, которое использует плоские буферы Google.deserialise google flat buffers
ФПС файл для схемы напитков:
namespace MyAlcoholist;
table Drink {
drink_type_name: string;
drink_company_name: string;
drink_brand_name: string;
drink_flavor_type_name : string;
liquid_color_type_name : string;
liquid_color_is_transparent : bool;
alcohol_vol : float;
calories_for_100g : uint;
global_image_id: uint;
drink_flavor_id: uint;
}
table Drinks { drinks:[Drink]; }
root_type Drinks;
скомпилирован с flatc -s drinks.fbs
, он сгенерировал JS файл drinks_generated.js. Все идет нормально.
Я использую следующий код в моем сервере nodejs подготовить и создать плоский буфер из массива:
flatBuffersUtil.js
var flatbuffers = require('../js/flatbuffers').flatbuffers;
var builder = new flatbuffers.Builder();
var drinks = require('../fbs/drinks_generated').MyAlcoholist; // Generated by `flatc`.
function drinkArrayToBuffer(drinkArray) {
var drinksVectArray = [];
drinkArray.forEach(function (element, index, array) {
var drinkObj = element;
var drinkBrandName = builder.createString(drinkObj.drink_brand_name);
var drinkCompanyName = builder.createString(drinkObj.drink_company_name);
var drinkflavorTypeName = builder.createString(drinkObj.drink_flavor_type_name);
var drinkTypeName = builder.createString(drinkObj.drink_type_name);
var liquidColorTypeName = builder.createString(drinkObj.liquid_color_type_name);
drinks.Drink.startDrink(builder);
drinks.Drink.addAlcoholVol(builder, drinkObj.alcohol_vol);
drinks.Drink.addCaloriesFor100g(builder, drinkObj.calories_for_100g);
drinks.Drink.addDrinkBrandName(builder, drinkBrandName);
drinks.Drink.addDrinkCompanyName(builder, drinkCompanyName);
drinks.Drink.addDrinkFlavorId(builder, drinkObj.drink_flavor_id);
drinks.Drink.addDrinkFlavorTypeName(builder, drinkflavorTypeName);
drinks.Drink.addDrinkTypeName(builder, drinkTypeName);
drinks.Drink.addGlobalImageId(builder, drinkObj.global_image_id);
drinks.Drink.addLiquidColorIsTransparent(builder, drinkObj.is_transparent);
drinks.Drink.addLiquidColorTypeName(builder, liquidColorTypeName);
var drink = drinks.Drink.endDrink(builder);
drinksVectArray.push(drink);
})
var drinksVect = drinks.Drinks.createDrinksVector(builder, drinksVectArray);
builder.finish(drinksVect);
var buf = builder.dataBuffer();
var drinksArray = drinks.Drinks.getRootAsDrinks(buf);
return buf;
}
module.exports.drinkArrayToBuffer = drinkArrayToBuffer;
использование flatBuffersUtil.js:
...
var data = flatBuffersUtil.drinkArrayToBuffer(result);
res.send(data);
клиент сделан с angularjs 1.5.0 , когда я получаю буфер, я пытаюсь создать объект из него, используя следующий код:
в главном индексном файле:
<script type="text/javascript" src="js/flatbuffers.js"></script>
<script type="text/javascript" src="js/fbs/drinks_generated.js"></script>
затем в угловой контроллер:
$http({
data: data,
method: 'POST',
url: 'https://myalcoholist.com:8888/drink/get_list/all_drinks',
}).then(function successCallback(response) {
var buffer = response.data;
var drinks = MyAlcoholist.Drinks.getRootAsDrinks(buffer);
deferred.resolve(drinks);
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
проблема заключается в том, что функция MyAlcoholist.Drinks.getRootAsDrinks(buffer);
выдает следующее сообщение об ошибке:
TypeError: bb.position is not a function
at Function.MyAlcoholist.Drinks.getRootAsDrinks (drinks_generated.js:256)
at successCallback (admin-drinks-controller.js:22)
at angular.js:15552
at m.$eval (angular.js:16820)
at m.$digest (angular.js:16636)
at m.$apply (angular.js:16928)
at g (angular.js:11266)
at t (angular.js:11464)
at XMLHttpRequest.u.onload (angular.js:11405)
Теперь. . Код функции в сгенерированном файле drinks_generated.js выглядит следующим образом:
MyAlcoholist.Drinks.getRootAsDrinks = function(bb, obj) {
return (obj || new MyAlcoholist.Drinks).__init(bb.readInt32(bb.position()) + bb.position(), bb);
};
так что bb должен быть байтовым типом с функцией position(), но то, что я получаю, является объектом байтов. Наверное, мне нужно придумать это сначала или как-то ... но это всего лишь предположение.
любые идеи?
обновления
ОК первый я пересмотрел свою функцию drinksArrayToBuffer к следующему коду:
function drinkArrayToBuffer(drinkArray) {
var drinksVectArray = [];
drinkArray.forEach(function (element, index, array) {
var drinkObj = element;
var drinkBrandName = builder.createString(drinkObj.drink_brand_name);
var drinkCompanyName = builder.createString(drinkObj.drink_company_name);
var drinkflavorTypeName = builder.createString(drinkObj.drink_flavor_type_name);
var drinkTypeName = builder.createString(drinkObj.drink_type_name);
var liquidColorTypeName = builder.createString(drinkObj.liquid_color_type_name);
drinks.Drink.startDrink(builder);
drinks.Drink.addAlcoholVol(builder, drinkObj.alcohol_vol);
drinks.Drink.addCaloriesFor100g(builder, drinkObj.calories_for_100g);
drinks.Drink.addDrinkBrandName(builder, drinkBrandName);
drinks.Drink.addDrinkCompanyName(builder, drinkCompanyName);
drinks.Drink.addDrinkFlavorId(builder, drinkObj.drink_flavor_id);
drinks.Drink.addDrinkFlavorTypeName(builder, drinkflavorTypeName);
drinks.Drink.addDrinkTypeName(builder, drinkTypeName);
drinks.Drink.addGlobalImageId(builder, drinkObj.global_image_id);
drinks.Drink.addLiquidColorIsTransparent(builder, drinkObj.is_transparent);
drinks.Drink.addLiquidColorTypeName(builder, liquidColorTypeName);
var drink = drinks.Drink.endDrink(builder);
drinksVectArray.push(drink);
})
var drinksVect = drinks.Drinks.createDrinksVector(builder, drinksVectArray);
drinks.Drinks.startDrinks(builder);
drinks.Drinks.addDrinks(builder, drinksVect);
var endDrinksOffset = drinks.Drinks.endDrinks(builder);
drinks.Drinks.finishDrinksBuffer(builder, endDrinksOffset);
var buf = builder.dataBuffer();
return buf;
}
сейчас в стороне сервера я могу deserialise буфера и использовать данные должным образом. проблема заключается в десериализации на стороне клиента.
после я шлю буфер, на стороне клиента получает следующий объект:
Object
bytes_: Object
position_: 7148
__proto__: Object
сейчас .. Я создал следующую функцию, чтобы преобразовать буфер объекта JSON на стороне клиента:
function drinksByteArrayToArray(buffer) {
var res = [];
var byteBuffer =new flatbuffers.ByteBuffer(buffer);
var drinks = MyAlcoholist.Drinks.getRootAsDrinks(byteBuffer);
var drinksLength = drinks.drinksLength();
for (var i=0;i<drinksLength;i++) {
var drink = drinks.drinks(i);
var drinkObj = {
drink_flavor_id: drink.drinkFlavorId(),
drink_type_name: drink.drinkTypeName(),
drink_company_name: drink.drinkCompanyName(),
drink_brand_name: drink.drinkBrandName(),
drink_flavor_type_name: drink.drinkFlavorTypeName(),
liquid_color_type_name: drink.liquidColorTypeName(),
is_transparent: drink.liquidColorIsTransparent(),
alcohol_vol: drink.alcoholVol(),
calories_for_100g: drink.caloriesFor100g(),
global_image_id: drink.globalImageId
}
res.push(drinkObj);
}
return res;
}
Когда я выслушиваю эту функцию, длина напитков равна нулю. поэтому буфер кажется пустым.
теперь я думаю, что проблема заключается в следующем коде:
var byteBuffer =new flatbuffers.ByteBuffer(buffer);
Я думаю, что мне нужно преобразовать данные в ByteBuffer каким-либо другим способом.
я понял, что мне нужно дать flatbuffers.ByteBuffer
массив байтов, так что я попытался сделать следующее вещь:
var byteBuffer =new flatbuffers.ByteBuffer(buffer.bytes_);
, но результат тот же.
любые идеи?
Да, похоже, вам нужно создать 'flatbuffers.ByteBuffer', используя массив байтов – Aardappel
Я согласен с Aardappel. Вероятно, вам нужно обернуть 'var buffer = response.data' в' flatbuffers.ByteBuffer'. (Что-то вроде 'var buffer = flatbuffers.ByteBuffer (response.data)'.) P.S. Кажется, вы вообще не используете 'drinksArray' в фрагменте' flatBuffersUtil.js'. 'var drinksArray = drinks.Drinks.getRootAsDrinks (buf); // unused' – MrHappyAsthma
Вы отправляете весь ByteBuffer. Попробуйте 'res.send (data.bytes())' – Aardappel