grpc-js三方库移植(二)——移植策略 原创

深开鸿董伟
发布于 2025-1-21 10:29
438浏览
0收藏

grpc-js三方库移植(二)——移植策略

简介

新建ets项目,创建library库,并将grpc-js主要功能代码拷贝至library目录下,进行原生node.js的ts代码进行arkTs环境下的node适配,解决编译问题,在应用demo中调用library导出的方法,进行功能调试。

具体步骤

一、项目构建

版本依赖

IDE版本 DevEco Studio 5.0.1 Release

下载路径:

https://developer.huawei.com/consumer/cn/download/

新建项目

新建应用,在应用中进行移植适配和功能调试

grpc-js三方库移植(二)——移植策略-鸿蒙开发者社区

新建library

新建Static Library

grpc-js三方库移植(二)——移植策略-鸿蒙开发者社区

配置文件

在entry模块中引入依赖 library库

grpc-js三方库移植(二)——移植策略-鸿蒙开发者社区

代码移植

grpc-js源代码路径

grpc-js三方库移植(二)——移植策略-鸿蒙开发者社区

ohos应用中grpc-js代码存放路径(将上图中的src目录下所有文件拷贝至library模块新建的ts目录下)

grpc-js三方库移植(二)——移植策略-鸿蒙开发者社区

二、基本使用

library库方法导出

library/Index.ets文件

import * as grpc from './src/main/ts'

export { grpc }
  • 1.
  • 2.
  • 3.

entry中ets后缀文件调用library库方法

import { grpc } from 'library'
  • 1.

entry中ts后缀文件调用library库方法

前置条件:将library/Index.ets 文件改为 library/Index.ts文件

grpc导入方法也与ets文件调用有所不同:

import { grpc } from "library/Index";
  • 1.

三、编译适配

由于grpc-js在node环境依赖的很多模块以及语法的检查上,和arkTs并不都一致,所以grpc-js内的ts代码放到library库下使用时,会出现一些语法以及代码功能上的错误,需要进行适配,总的思路就是,用arkTs的模块来代替node原生但在arkTs不支持的模块,首先是确保编译可以通过,然后再进行功能的调试。

功能模块查找替换

示例1(arkTs中存在同功能模块):

原代码:

export interface CaCertificateUpdate {

  caCertificate: Buffer;

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

Buffer是node.js的原生类型,arkTs不存在Buffer类型,使用@ohos.buffer模块的buffer.Buffer类型替换

import buffer from '@ohos.buffer';
export type Buffer = buffer.Buffer;
  • 1.
  • 2.
示例2(arkTs中不存在同功能模块,需要编写wrapper):

原代码

import { promises as dns } from 'dns';

private alternativeResolver = new dns.Resolver();
this.alternativeResolver.setServers([target.authority]);
this.alternativeResolver.resolve4(hostname),
this.alternativeResolver.resolve6(hostname),
this.alternativeResolver.resolveTxt(hostname);

const addressList = await dns.lookup(hostname, { all: true });
return dns.resolveTxt(hostname);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

arkTs中不存在dns模块,无法使用类似的导入,这时候需要编写一个wrapper,实现一个dns的类,使其具备node.js中dns模块在grpc-js里面有用到的功能

编写dns wrapper:

//  创建WrapperResolver类,用于创建dns对象实例,constructor中打印log,后续代码调试时可查看调用信息
export class WrapperResolver {
  private DOMAIN = 0x8691
  private TAG = 'WrapperResolver'

  private serverList: string[];

  constructor() {
    hilog.info(this.DOMAIN, this.TAG, 'create Resolver');
  }

  public getServers(): string[] {
    return [
      '8.8.8.8',
      '2001:4860:4860::8888',
      '8.8.8.8:1053',
      '[2001:4860:4860::8888]:1053',
    ]
  }

  public setServers(paramList: string[]) {
    this.serverList = paramList;
  }

  public resolve(){

  }

  public resolve4(param: string){
    return param;
  }

  public resolve6(param: string){
    return param;
  }

  public resolveAny(){}

  public resolveCaa(){}

  public resolveCname(){}

  public resolveMx(){}

  public resolveNaptr(){}

  public resolveNs(){}

  public resolvePtr(){}

  public resolveSoa(){}

  public resolveSrv(){}

  public resolveTxt(param: string): Promise<string[][]>{
    return [][param];
  }

  public reverse(){}
}

// dns实例
export class dns {
  static lookup(hostname: string, arg1: { all: boolean }) {
    let result:Promise<LookupAddress[]>;
    return result
  }

  static Resolver() {
    return new WrapperResolver();
  }

  static resolveTxt(hostname: string): Promise<string[][]> {
    return [][hostname];
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.

替换dns wrapper原代码调用:

import { dns, WrapperResolver } from './wrapper/dns';

private alternativeResolver: WrapperResolver;
this.alternativeResolver = new WrapperResolver();
this.alternativeResolver.setServers([target.authority]);
this.alternativeResolver.resolve4(hostname),
this.alternativeResolver.resolve6(hostname),
this.alternativeResolver.resolveTxt(hostname);

const addressList = await dns.lookup(hostname, { all: true });
return dns.resolveTxt(hostname);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

可以看出来,除了类是单独构建并替换了原有的导入,代码中的改动是非常小的,只在创建实例的地方因为调用方法不同有些许改动,这样编写wrapper,代码后续维护也非常方便,只需要改动wrapper即可。

由于植入的wrapper定义的部分接口并没有具体的实现,所以接口调用时必须打印一些有辨识度的log,否则调试功能,程序运行时可能不知道执行到哪一步了。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报


回复
    相关推荐