Как вызвать функцию JavaScript (сгенерированную из машинописного текста), захваченную в модуле «System.register ()» при использовании Google protobuf? - PullRequest
0 голосов
/ 29 июня 2018

Обновление : Похоже, проблема возникла из-за protobuf. Я в порядке и с другим решением, которое помогает мне решить проблемы с Google protobuf. Эта проблема сводится к:

  • Как интегрировать Google protobuf с Typescript / Javascript для браузера?

У меня есть вопрос ниже для будущей цели.


Мы переместили наше приложение с Javascript на Typescript для очевидных преимуществ ООП и т. Д.
Ранее вызывать прямую функцию JavaScript из HTML было так же просто, как:

<script>window.MyFunction()</script>

Теперь с Typescript все файлы объединены в один автоматически сгенерированный файл .js.
В этом отдельном файле отдельные коды каждого файла изолированы в System.register(). Обычно это выглядит примерно так:

System.register("<filename>", ["<import_1>", ..., "<import_N>"], 
  function (exports_13, context_13) {
    "use strict";

...

  function MyFunction () { ... } // somewhere inside the external function
}

Короче говоря, все, что написано в файле .ts, упаковано в неназванную функцию после запуска компилятора tsc.

Теперь я не знаю, как вызвать функцию, которая находится внутри другой функции, которая, в свою очередь, указана в System.register(...)

Вопрос : Каков правильный синтаксис для вызова такой функции извне из HTML-файла?

<script> ??? </script>

Обновление :

HTML пытается вызвать в теге body следующим образом:

  <script>
    System.import("Main").then(  // Main.ts is one of the file
      function (module)
      {
        throw 0;  // Temporary, to see if we reach till here
        module.main();  // "main()" is the function, which is the entry point
      });
  </script>

В своем коде я использую "browserify", чтобы использовать Google protobuf для JS. Ошибка возникает только для файлов, связанных с protobuf. Эти определения и исходные файлы представлены в форматах .d.ts и .js.
Ошибка примерно такая:

js: Uncaught (in promise) Error: Fetch error: 404 NOT FOUND
Instantiating http://localhost:50000/folder/external/Server_pb
Loading http://localhost:50000/folder/external/_External
Loading Main 

Обратите внимание, что 50000 - это временный порт, а папка - это любая папка, в которой хранятся файлы .js. «Server_pb» - это созданный пользовательский файл protobuf.

Моя проблема может быть точно описана как эта ссылка .


Похожие:

1 Ответ

0 голосов
/ 08 июля 2018

С "google-protobuf" возникают проблемы при использовании в стиле systemjs. Похоже, Google создал его только для nodejs. : -)
Чтобы иметь возможность использовать protobuf в Javascript для браузера , есть несколько вещей, которые мы должны сделать вручную. Такая ручная стандартная работа может быть выполнена с использованием некоторых сценариев.

Я даю итерационный способ, как этого добиться:

  1. Первым шагом является создание protobuf для JS и TS. Используйте следующую команду для того же:

    protoc <file1.proto> <file2.proto> ... <fileN.proto>
    --proto_path=<proto_folder> \
    --cpp_out=<cpp_folder> \
    --js_out=import_style=commonjs,binary:<js_folder> \
    --ts_out=import_style=commonjs,binary:<ts_folder>

  2. Обратите внимание, что мы используем commonjs (а не systemjs). Легенды:

    • <proto_folder> = путь к папке, где хранятся все эти file1/2/N.proto файлы
    • <cpp_folder> = путь к папке, в которой вы хотите хранить файлы c ++ file1/2/N.pb.cc/h
    • <js_folder> = папка, в которой вы хотите хранить file1/2/N_pb.js файлы
    • <ts_folder> = папка, в которой вы хотите хранить file1/2/N_pb.d.ts файлы
  3. Теперь во всех файлах .d.ts (определение Typescript) есть определенные строки кода, которые приведут к ошибкам компилятора. Нам нужно прокомментировать эти строки. Делать вручную очень громоздко. Следовательно, вы можете использовать sed (или ssed в Windows, gsed в Mac). Например, строки, начинающиеся с

    • sed -i "s/^ static extensions/\/\/ static extensions/g" *_pb.d.ts;
    • То же, что и выше для static serializeBinaryToWriter
    • То же, что и выше для static deserializeBinaryFromReader
    • sed -i "s/google-protobuf/\.\/google-protobuf/g" *_pb.d.ts; // "./google-protobuf" is correct way to import
  4. Теперь при генерации *_pb.d.ts компилятор protoc не следует упаковке для Typescript. Например, если в вашем fileN.proto вы упомянули package ABC.XYZ, то fileN.pb.h будет заключен в namespace ABC { namespace XYZ { ... } }. То же самое не происходит в случае Typescript. Поэтому мы должны вручную добавить их в файл. Однако здесь это не будет простым поиском / заменой, как указано выше. Скорее, мы должны найти только первое вхождение любого export class (которое является сгенерированным прото) и обернуть пространства имен. Ниже приведена команда:

    • sed -i "0,/export class/{s/export class/export namespace ABC { export namespace XYZ {\\n &/}" fileN_pb.d.ts;
    • sed -i -e "\$a} }" fileN_pb.d.ts;
  5. Первоначальный импорт пакета google-protobuf должен иметь префикс ./ в случае сгенерированного файла _pb.js, а также

    • sed -i "s/google-protobuf/\.\/google-protobuf/g" *_pb.js;
  6. Теперь скомпилируйте пользовательские файлы Typescript с помощью tsc -p "<path to the tsconfig.json>", где tsconfig.json может выглядеть следующим образом (см. Стрелку):

    { "compileOnSave": true, "compilerOptions": { "removeComments": true, "preserveConstEnums": true, "module": "CommonJS", <======= "outDir": "<path to generated js folder>", }, "include": ["../*"], "files": ["<path to file1.ts>", ..., "<path to file2.ts>" }

  7. Теперь очень важный шаг . Все ссылки на сгенерированные файлы *_pb.d.ts должны быть указаны в 1 вашего пользовательского файла. Этот пользовательский файл может содержать оболочки вокруг сгенерированных классов, если это необходимо. Это поможет ограничить замену строк только в этом файле, что будет объяснено на следующем шаге. Например, создайте пользовательское имя файла как MyProtobuf.ts и import your proto следующим образом:

    • import * as proto from './fileN; // from fileN.d.ts
  8. На предыдущем шаге важно отметить, что имя "proto" имеет решающее значение. С этим именем файлы .js генерируются автоматически. Если в вашем проекте есть несколько прототипов, вам, возможно, придется создать еще 1 файл, который экспортирует их все, а затем импортировать этот 1 файл:

    • // in 'MyProtobufExports.ts' file
      export * from './file1'
      export * from './file2'
      export * from './fileN'
    • import * as proto from './MyprotobufExports // in MyProtobuf.ts file
  9. С помощью 2 выше этапов, использование protobuf as, var myClass = new proto.ABC.XYZ.MyClass;

  10. Теперь продолжение важного шага , о котором мы говорили выше. Когда мы генерируем эквивалентные _pb.js и наши пользовательские .js файлы, специальный символ-имя proto все равно не будет найден. Хотя все завернуто. Это связано с тем, что автоматически сгенерированные файлы JS (из файлов TS) объявят var proto. Если мы это прокомментируем, проблема исчезнет.

    • sed -i "s/var proto = require/\/\/ &/g" Protobuf.js;
  11. Последний шаг - поместить browserify для всех файлов .js в один файл, как показано ниже. Из-за этого будет только один .js файл, с которым нам приходится иметь дело [хорошо или плохо]. В этой команде порядок очень важен. file1_pb.js должен предшествовать file2_pb.js, если file1.proto импортируется file2.proto или наоборот. Если нет import, то порядок не имеет значения. В любом случае _pb.js должен предшествовать пользовательским .js файлам.

    • browserify --standalone file1_pb.js fileN_pb.js MyProtobuf.js myfile1.js myfileN.js -o=autogen.js
  12. Поскольку код просматривается с помощью браузера, вызов функции может быть выполнен следующим образом:

    • window.main = function (...) { ... } // entry point somewhere in the fileN.ts file
      <script>main(...)</script> // in the index.html

Только с помощью описанных выше шагов я могу заставить "google-protobuf" работать в моем проекте для браузера.

...