如何调用捕获在"System.register()"中的javascript函数(从打字稿生成). Google protobuf时使用模块? [英] How to invoke a javascript function (generated from typescript) trapped within "System.register()" module while using Google protobuf?

查看:161
本文介绍了如何调用捕获在"System.register()"中的javascript函数(从打字稿生成). Google protobuf时使用模块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:看来,问题是由于protobuf引起的.我也可以使用其他解决方案,这些解决方案可以帮助我解决Google protobuf问题.这个问题可以归结为:

Update: It seems that, the problem is coming due to protobuf. I am fine with other solution as well, which help me to fix the Google protobuf issues. This problem boils down to:

  • 如何为浏览器集成Google protobuf与Typescript/Javascript?

为了将来的目的,我保留下面的问题.

I am retaining below question for the future purpose.

我们已将应用程序从Javascript移至Typescript,以实现OOP等的明显优势.
先前从HTML调用直接javascript函数的方法很简单:

We have moved our application from Javascript to Typescript for obvious advantages of OOP etc..
Earlier invoking a direct javascript function from Html was as straight forward as:

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

现在有了Typescript,所有文件都合并到一个自动生成的.js文件中.
在此单个文件中,每个文件的单独代码都在System.register()中隔离.通常看起来像这样:

Now with Typescript, all the files are combined into a single autogenerated .js file.
In this single file, individual code of every file are isolated within System.register(). It typically looks something like:

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

...

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

简而言之,运行tsc编译器后,.ts文件中编写的所有内容都被包装在一个未命名的函数中.

In short, everything written within the .ts file is wrapped in an unnamed function after running the tsc compiler.

现在,我不知道如何调用一个函数,该函数被困在另一个函数中,该函数又列在System.register(...)

Now, I don't know how to invoke a function, which is trapped inside another function, which is in turn listed under System.register(...)

问题:从HTML文件从外部调用该函数的正确语法是什么?

Question: What is the correct syntax to invoke such function externally from an Html file?

<script> ??? </script>

更新:

HTML尝试通过以下方式在body标签中调用:

The HTML tries to invoke in following way in the body tag:

  <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 for JS.该错误仅适用于与protobuf相关的文件.这些定义和源文件以.d.ts和.js格式显示.
错误如下所示:

In my code, I am using "browserify" to be able to use the Google protobuf for JS. The error comes for the protobuf related files only. Those definition and source files are present in .d.ts and .js formats.
The error is something like below:

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文件.

Note that, 50000 is a temporary port and the "folder" is just any folder where the .js are kept. The "Server_pb" is a custom protobuf file generated.

我的问题可以恰当地描述为与此链接 .

My problem can be aptly described quite similar as this link.

相关:

  • What is mean by System.register in JS file?
  • How to call a named module from a bundle (<-- can be helpful, but don't know the syntax as a newbie)
  • How to start a Typescript app with SystemJS modules? (nearly duplicate, but unable to solve the problem with this approach yet)
  • How do I get TypeScript to bundle a 3rd party lib from node_modules? (seems like another close match; trying to dig into this right now to fix the protobuf problem)

推荐答案

使用"google-protobuf"时,以systemjs的方式使用时会出现问题.看来Google只为nodejs创建了它. :-)
为了能够在浏览器中使用Javascript中的 protobuf ,我们需要手动完成一些操作.这样的手动样板工作也可以使用一些脚本来完成.

With "google-protobuf" there are issues when used in the fashion of systemjs. It seems that Google has created it only for the nodejs. :-)
To be able to use the protobuf in Javascript for the browser, there are few things which we have to do manually. Such manual boilerplate work can be done using some scripts as well.

我正在为实现这一目标提供一种迭代的方式:

I am giving an iterative way, on how to achieve this:

  1. 第一步是为JS和TS生成protobuf.使用以下命令进行相同操作:

  1. The first step is to generate the protobuf for both JS and TS. Use following command for the same:

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>

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>

请注意,我们使用的是commonjs(而不是systemjs).传说:

Note that, we are using the commonjs (and not systemjs). Legends:

  • <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文件的文件夹
  • <proto_folder> = folder path where all these file1/2/N.proto files are stored
  • <cpp_folder> = folder path where you want the c++ file1/2/N.pb.cc/h files to be stored
  • <js_folder> = folder where you want the file1/2/N_pb.js files to be stored
  • <ts_folder> = folder where you want the file1/2/N_pb.d.ts files to be stored

现在在所有.d.ts(Typescript定义)文件中,都有某些代码行,这些行会导致编译器错误.我们需要对这些行进行注释.手动进行非常麻烦.因此,您可以使用sed(在Windows中为ssed,在Mac中为gsed).例如,以

Now in all the .d.ts (Typescript definition) files, there are certain code lines, which will give compiler errors. We need to comment these lines. Doing manually, is very cumbersome. Hence you may use sed (or ssed in Windows, gsed in Mac). For example, the lines starting with,

  • 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
  • sed -i "s/^ static extensions/\/\/ static extensions/g" *_pb.d.ts;
  • same as above for static serializeBinaryToWriter
  • same as above for static deserializeBinaryFromReader
  • sed -i "s/google-protobuf/\.\/google-protobuf/g" *_pb.d.ts; // "./google-protobuf" is correct way to import

现在,在生成*_pb.d.ts时,protoc编译器不会遵循Typescript的打包要求.例如,如果在fileN.proto中提到了package ABC.XYZ,则fileN.pb.h将被包装在namespace ABC { namespace XYZ { ... } }中.对于Typescript,不会发生相同的情况.因此,我们必须手动将它们添加到文件中.但是,这里将不会像上面那样简单地查找/替换.相反,我们只需要查找任何export class的首次出现(它是生成的原型)并包装名称空间.因此,下面是命令:

Now, while generating the *_pb.d.ts, the protoc compiler doesn't follow the packaging for Typescript. For example, if in your fileN.proto, you have mentioned package ABC.XYZ, then the fileN.pb.h will be wrapped in namespace ABC { namespace XYZ { ... } }. The same doesn't happen in the case of Typescript. So we have to manually add these in the file. However, here it won't be a simple find/replace as above. Rather, we have to find only the first occurance of any export class (which is of generated proto) and wrap the namespaces. So below is the command:

  • 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;
  • 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;

在生成_pb.js文件的情况下,google-protobuf程序包的初始导入也必须以./为前缀

Initial importing of the google-protobuf package has to be prefixed with ./ in the case of generated _pb.js file as well

  • sed -i "s/google-protobuf/\.\/google-protobuf/g" *_pb.js;

现在使用tsc -p "<path to the tsconfig.json>"编译自定义Typescript文件,其中tsconfig.json可能看起来像(见箭头):

Now compile the the custom Typescript files with tsc -p "<path to the tsconfig.json>", where the tsconfig.json may look like (see arrow):

{ "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>" }

{ "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>" }

现在非常重要的一步.对所生成的*_pb.d.ts文件的所有引用都应在自定义文件的1中引用.如果需要,该自定义文件可能包含围绕生成的类的包装.这将有助于限制仅在该文件中的字符串替换,这将在后续步骤中进行说明.例如,创建一个自定义文件名,如MyProtobuf.tsimport您的proto,如下所示:

Now a very important step. All the references to the the generated *_pb.d.ts files, should be referred in 1 of your custom file. That custom file may contain the wrappers around the generated classes if it's required. This will help in limiting string replacement only in that file, which is explained in the upcoming step. For example, create a custom file name as MyProtobuf.ts and import your proto as following:

  • import * as proto from './fileN; // from fileN.d.ts

在上面的步骤中,重要的是要注意名称"proto"是至关重要的.使用该名称,将自动生成.js文件.如果您的项目中有几个原始文件,那么您可能还需要再创建1个文件以导出所有文件,然后导入该1个文件:

In above step, it's important to note that the name "proto" is crucial. With that name, the .js files are auto generated. If there are several proto files in your project, then you may have to create yet 1 more file which exports all of them and then import that 1 file:

  • // in 'MyProtobufExports.ts' file
    export * from './file1'
    export * from './file2'
    export * from './fileN'
  • import * as proto from './MyprotobufExports // in MyProtobuf.ts file
  • // in 'MyProtobufExports.ts' file
    export * from './file1'
    export * from './file2'
    export * from './fileN'
  • import * as proto from './MyprotobufExports // in MyProtobuf.ts file

通过上述两个步骤,protobuf的用法为var myClass = new proto.ABC.XYZ.MyClass;

With above 2 steps, the usage of the protobuf as, var myClass = new proto.ABC.XYZ.MyClass;

现在是我们上面讨论的重要步骤的继续.当我们生成等效的_pb.js和我们的自定义.js文件时,仍然会以某种方式找不到特殊的名称符号proto.即使一切都包裹好了.这是因为自动生成的JS文件(来自TS文件)将声明var proto.如果我们对此发表评论,那么这个问题就解决了.

Now the continuation of the important step we discussed above. When we generate the equivalent _pb.js and our custom .js files, still the special name-symbol proto will not be found somehow. Even though everything is wrapped. This is because the autogenerated JS files (from TS files), will declare a var proto. If we comment that then, that issue is gone.

  • sed -i "s/var proto = require/\/\/ &/g" Protobuf.js;

最后一步是将所有.js文件上的browserify放入一个文件中,如下所示.因此,只有一个.js文件,我们必须处理[good or bad].在此命令中,排序非常重要.如果file1.proto是通过file2.proto导入的,则file1_pb.js应该在file2_pb.js之前,反之亦然.如果没有import,则顺序无关紧要.在任何情况下,_pb.js应该位于自定义.js文件之前.

The final step is to put the browserify on all the .js files into a single file, as below. Due to this, there will be only single .js file, we have to deal with [good or bad]. In this command, the ordering is very important. file1_pb.js should come before file2_pb.js, if file1.proto is imported by file2.proto or vice a versa. If there is no import then the order doesn't matter. In any case the _pb.js should come before the custom .js files.

  • browserify --standalone file1_pb.js fileN_pb.js MyProtobuf.js myfile1.js myfileN.js -o=autogen.js

由于代码已被浏览器化,因此可以通过以下方式完成函数的调用:

Since the code is browserified, the calling of function can be done in following way:

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

仅通过上述步骤,我就可以在我的浏览器项目中使用"google-protobuf".

With the above steps only, I am able to make the "google-protobuf" work within my project for the browser.

这篇关于如何调用捕获在"System.register()"中的javascript函数(从打字稿生成). Google protobuf时使用模块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆