积分80 / 贡献0

提问0答案被采纳0文章4

[经验分享] grpc-js三方库移植(二)——移植策略 原创

深开鸿_董伟 显示全部楼层 发表于 昨天 10:27

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/

新建项目

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

createModule.png

新建library

新建Static Library

newLibrary.png

配置文件

在entry模块中引入依赖 library库

entryJson.png

代码移植

grpc-js源代码路径

grpcJs.png

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

ohosGrpc.png

二、基本使用

library库方法导出

library/Index.ets文件

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

export { grpc }

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


import { grpc } from 'library'

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

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

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


import { grpc } from "library/Index";

三、编译适配

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

功能模块查找替换

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

原代码:


export interface CaCertificateUpdate {

  caCertificate: Buffer;

}

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


import buffer from '@ohos.buffer';
export type Buffer = buffer.Buffer;
示例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);

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];
  }
}

替换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);

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

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

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部