自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(174)
  • 资源 (2)
  • 论坛 (6)
  • 收藏
  • 关注

原创 TypeScript里的类型合并操作符&

通过 & 运算符可以将现有的多种类型叠加到一起成为一种类型:type PointX = { x: number; };type PointY = { y: number; }type Point = PointX & PointY;const point:Point = { x: 1, y: 1};编译之后的JavaScript代码:var point = { x: 1, y: 1 };...

2020-11-30 22:27:52 100

原创 SAP Spartacus build error之后的retrigger方式

如果某个pull request 触发的travis build失败之后,可以到Travis website上查看build的错误日志:也可以在Travis CI上重新触发build:更多Jerry的原创文章,尽在:“汪子熙”:

2020-11-30 21:43:55 27

原创 通过环境变量注入的方式启动SAP Spartacus B2B模块

Windows命令行下,执行如下shell脚本:set SPARTACUS_B2B=trueset SPARTACUS_BASE_URL='https://spartacus-dev3.eastus.cloudapp.azure.com:9002'进入node交互式模式,输入process, 回车,看到SPARTACUS_B2B_和SPARTACUS_BASE_URL成功被注入之后,ng serve --open启动即可:更多Jerry的原创文章,尽在:“汪子熙”:...

2020-11-30 19:36:11 33

原创 SAP Spartacus 3.0和B2B特性相关的手动测试

Admin tasks:sign in as admincreate a unitedit a unitcreate a sub unitcreate a buyer and assign to a unitedit the buyercreate a cost centercreate a budgetassign a budget to a cost centeradd an address to a unitadd another addressdelete first on

2020-11-30 16:56:40 30

原创 TypeScript里的工具类型Partial的用法

在SAP Spartacus的源代码里我们可以观察到很多Partial的使用场景:Partial 可以快速把某个接口类型中定义的属性变成可选的(Optional):interface People { age: number; name: string;}const Jerry:People = { age: 10, name: 'Jerry'};const Tom: People = { name: 'Tom'}上述代码会发生编译时错误:1.ts:11:7 -

2020-11-30 14:52:23 192

原创 TypeScript里的空值合并运算符(双问号)用法

当左侧操作数为 null 或 undefined 时,其返回右侧的操作数,否则返回左侧的操作数。例子:const foo = null ?? 'default string';编译后的JavaScript代码:var _a;var foo = (_a = null) !== null && _a !== void 0 ? _a : 'default string';可见,这个例子,foo必定为default string, 因为编译后的JavaScript代码里,已经能看到n

2020-11-30 14:37:40 146

原创 TypeScript里的可选链(Optional Chaining,即问号)用法

用途:遇到null或者undefined时可以立即停止表达式的运行。看个例子:let a = { b: 1};const val = a?.b;编译之后生成的JavaScript代码:var a = { b: 1 };var val = a === null || a === void 0 ? void 0 : a.b;可见,如果a为null或者void 0,会直接返回void 0,而不会接着执行a.b因此,以后我们可以不需要编写形如if( a && a.b){}

2020-11-30 14:23:23 98

原创 Angular jasmine TestBed.configureTestingModule的工作原理

调试入口:单元测试代码里定义的imports和providers数据,类型为TestModuleMetadata,已经注入到变量moduleDef里了:TestBed的实现是R3TestBed, 调用compiler的configureTestingModule方法进行配置:this:R3TestBedCompiler:更多Jerry的原创文章,尽在:“汪子熙”:...

2020-11-29 21:20:43 34

原创 Jerry Wang的自我介绍和linkedin,欢迎大家添加 - for 云加社区评审海报

公众号:汪子熙SAP全球社区导师,SAP全球技术大使,在SAP社区发表了超过600篇的技术博客在SAP技术领域从业14年,参与多款SAP产品的设计和研发工作求知欲强烈,喜欢不断涉足新领域的知识,最近由于生了一场大病,对神经外科知识也有了一定的了解擅长领域:SAP应用技术我是一名普通的软件开发人员,技术写作让生性内向的我认识了很多志同道合,同样对企业应用设计开发有着浓厚兴趣的朋友们,也帮助了一些计划和刚刚进入这个领域的朋友们,从中我认识到了自己的价值。在书写一篇篇技术文章时,我也在书写着自己的人

2020-11-29 19:52:13 83

原创 Jerry Wang的微信小程序开发系列文章

微信小程序开发系列一:微信小程序的申请和开发环境的搭建微信小程序开发系列二:微信小程序的视图设计微信小程序开发系列教程三:微信小程序的调试方法微信小程序开发系列四:微信小程序之控制器的初始化逻辑微信小程序开发系列五:微信小程序中如何响应用户输入事件微信小程序开发系列六:微信框架API的调用微信小程序开发系列七:微信小程序的页面跳转...

2020-11-29 14:37:29 45

原创 Jerry Wang的微信公众号开发系列文章

微信程序开发系列教程(一)开发环境搭建微信程序开发系列教程(二)使用JavaScript给微信用户发送消息微信程序开发系列教程(二)微信订阅号+人工智能问答服务微信程序开发系列教程(三)使用微信API给微信用户发文本消息微信程序开发系列教程(四)使用微信API创建公众号自定义菜单...

2020-11-29 14:35:24 41

原创 Jerry Wang的SAP UI5源代码深入剖析系列文章

一个用于SAP UI5学习的脚手架应用,没有任何后台API的依赖通过最简单的button控件,深入学习SAP UI5框架代码系列之零深入学习SAP UI5框架代码系列之一:UI5 Module的懒加载机制深入学习SAP UI5框架代码系列之二:UI5 控件的渲染器深入学习SAP UI5框架代码系列之三:HTML原生事件 VS UI5 Semantic事件UI5控件元数据实现细节 - 正在写作中UI5控件的实例数据实现细节 - 正在写作中UI5控件数据绑定的实现原..

2020-11-29 14:33:15 37

原创 Angular jasmine单元测试框架TestBed.inject的执行原理

单步调试这段代码:TestBed用于单元测试代码里创建Component和service实例。injectionToken即传入TestBed.inject的function:还是delegate给TestModuleRef的injector进行常规的injection操作:Records里早就被注入好了:因为value早就ready了,不需要进入第11243行的record.factory()重新生成实例,直接返回即可:更多Jerry的原创文章,尽在:“汪子熙”:.

2020-11-28 23:21:43 42

原创 Error: <spyOn> : handleError() method does not exist

单元测试出错:Error: : handleError() method does not existUsage: spyOn(, )at at UserContext.apply (http://localhost:9876/karma_webpack/src/global-message/http-interceptors/http-error.interceptor.spec.ts:121:9)at ZoneDelegate.invoke (http://localhost:9876/

2020-11-28 23:11:39 62

原创 Angular jasmine单元测试框架spied method的调用记录数据结构

基于UnknownErrorHandler的handleError方法创建一个spy 方法:第40行调用的是spied之后的新方法:因为调用的是Spied之后的wrapper方法,在wrapper方法的执行里有track逻辑,即记录方法调用使用的参数和response:所有被spy之后的方法调用都记录在jasmine的内部数据结构calls里,它是一个大的数组:更多Jerry的原创文章,尽在:“汪子熙”:...

2020-11-28 22:17:29 62

原创 Angular jasmine单元测试框架spec的运行时数据结构

以我单元测试里这段代码为例:通过describe函数创建一个suite,即spec的集合:真正的spec由函数it创建:其中expectable是human readable的字符串描述信息,描述该spec具体要测试哪些东西,assertion就是具体的包含单元测试的代码。spec内部的expect方法调用:调用env.expect:使用spec的expectationFactory创建一个expectation:spec变量里包含了执行通过的expectation和执行失败的expec

2020-11-28 22:03:44 49

原创 Angular jasmine单元测试框架里expect.toHaveBeenCalled的工作原理

第120行给handler.handleError方法注入spy后,第121行代码flush HTTP Mock request会触发handler.handleError(的wrap实现)调用。第123行代码检测该方法是否真正被调用过。首先执行expect(handler.handleError), 给handler.handleError创建一个spec:实际上调用currentRunnable的expect方法:this指向spec,actual就是被wrap后的方法。使用expectat

2020-11-28 21:59:27 111

原创 Angular jasmine单元测试框架里spyOn的创建原理

准备针对handler的handleError方法创建spy:保存原始方法的信息到变量originalMetho里:利用spyFactory.createSpy创建spied版本的新方法:wrap就是spyOn执行完毕后,原始被spied方法被取而代之的新方法:如下图所示,handler的handleError方法已经被替换成了wrapper:一旦执行上图的第40行代码,就进入wrap的执行逻辑:因为调用的是wrapper,wrapper里有track逻辑:所有被spy之后的方

2020-11-28 18:06:37 30

原创 SAP Spartacus HTTP请求的错误处理机制

HttpInterceptor来自Angular标准库,而构造函数里注入的handlers,类型为HttpErrorHandler,后者是Spartacus自己实现的。HttpErrorHandler是一个abstract class:responseStatus:每个HttpErrorHandler的子类,负责处理一种HTTP的错误状态。HttpErrorInterceptor的handleErrorResponse:根据response的状态找到对应的handler,再调用handler的h

2020-11-28 16:31:50 41

原创 Angular NgModule providers字段维护了多个字段后的初始化实现

下图是Angular依赖注入运行时处理的multi records数据结构:对应我在NgModule的providers区域里定义的providers record:在一个for循环里依次按顺序注入这8个types对应的值:这也解释了我之前的发现,如果通过provide定义了相同的injection token,但是useClass的providers不一样,则后定义的useClass生效。这是其中的一次循环:进入UnknownErrorHandler的实例化过程:执行完代码第14行

2020-11-27 20:51:59 37

原创 如何在Slack里连接微软One Drive

我们在Slack里连接微软One Drive之后,就可以在Slack里给其他人发送文件时,直接选择One Drive里的文件。点击Connect按钮,弹出来一个网页:微软One Drive正在请求访问SAP Champions和SAP Mentor的slack workspace,询问用户是否赋予One drive该权限。点击Allow之后,收到一封提示邮件,已经在Slack里成功安装了One Drive App:接下来,在Slack里给别人发文件时,可以直接选择One Drive里的文件了

2020-11-27 20:21:45 33

原创 今日头条PC端的状态管理,使用的实现库是Redux

打开今日头条PC端的个人主页:发送一个类型为content/getList的Action从头条服务器取数据,采取分页读取,page size为10. 意思是取10条我已经发布的头条内容到个人中心并渲染:在content/mergeIn这个action的payload区域,内看到成功从头条后台服务器读取完毕的10条头条内容:loading状态从true变为false,说明加载完毕:文章的摘要存放在字段article_attr.abstract里:文章的其他详细信息,比如guid,创建时间,作

2020-11-27 18:01:48 32

原创 Angular应用里使用import直接导入到应用代码里的class,在运行时的表现

如图:import { HttpErrorHandler } from './ngrxdemo/service/unittest-study/abstract-test';直接打印:打印出的是这个类的源代码:很有意思的是,在Chrome开发者工具里无法直接显示这个从import里导出的“变量”:这个import导出的变量有且仅有这些属性可供打印输出:更多Jerry的原创文章,尽在:“汪子熙”:...

2020-11-27 18:00:35 24

原创 测试:abstract class不允许出现在Angular依赖注入框架的providers区域内

测试用的service类:import { Injectable } from '@angular/core';@Injectable({ providedIn: 'root', })export abstract class HttpErrorHandler{ constructor(){} abstract handleError( ): void;}@Injectable({ providedIn: 'root', })export

2020-11-27 15:09:21 31

原创 Angular依赖注入机制的一个错误消息:Error Cannot instantiate cyclic dependency!

例子:import { Injectable } from '@angular/core';@Injectable({ providedIn: 'root', })export abstract class HttpErrorHandler{ abstract handleError( ): void;}@Injectable({ providedIn: 'root', })export class UnKnownHandler { han

2020-11-27 14:53:40 91

原创 Angular 依赖注入机制根据providers定义生成注入实例的框架代码

/** * Converts a `SingleProvider` into a factory function. * * @param {?} provider provider to convert to factory * @param {?=} ngModuleType * @param {?=} providers * @return {?} */function providerToFactory(provider, ngModuleType, providers) { .

2020-11-27 11:01:24 30

原创 Angular依赖注入useClass的实例创建位置

用@NgModule在providers定义了MyService token用useClass来提供:MyNewService的初始化过程:InjectionToken:this.records: 一个巨大的map,key为injection token,value的数据结构如下图所示:useClass的实例化,在代码17207的record.factory方法调用里进行:更多Jerry的原创文章,尽在:“汪子熙”:...

2020-11-27 10:56:12 28

原创 关于Angular @Injectable的几种测试情况

我有一个服务类:export class MyNewService { seed: number; text: 'NewService'; constructor(){ this.seed = Number((Math.random() * 100).toFixed(0)); console.log('diablo constructor called: ' + this.seed); }}在app.module.ts里providers区域的定义:测试场景1M

2020-11-27 10:53:27 35

原创 为什么Spartacus单元测试里对http返回的Observable对象调用subscribe时,会触发依赖注入的框架代码

今天我工作发现,一旦下面单元测试代码第109行,即subscribe方法单步调试进去:会触发HTTP请求真正的执行,即请求发送给服务器:试图获取HTTP_INTERCEPTORS这个injection token:当前以HTTP_INTERCEPTORS为token的records:这里使用factory方法初始化HttpErrorInterceptor实例:因为HTTPErrorInterceptor有一个指向HTTPErrorHandlers的依赖:因此又需要注入HTTPErr

2020-11-26 19:01:17 28

原创 Angular HttpClient.get的实现单步调试

进入get方法:request方法实现的源代码:@Injectable()export class HttpClient { constructor(private handler: HttpHandler) {} /** * Sends an `HTTPRequest` and returns a stream of `HTTPEvents`. * * @return An `Observable` of the response, with the respons.

2020-11-26 18:44:27 26

原创 SAP Spartacus里的HTTPErrorInterceptor的设计原理

HTTPErrorInterceptor有一个protected的成员,handlers,类型为HttpErrorHandler:HttpErrorHandler是一个abstract class:其子类需要实现handleError这个定义在其上的abstract方法:父类的responseStatus字段,需要子类自行去填充,这样HTTPErrorInterceptor才能检索到handler:依赖关系如图:更多Jerry的原创文章,尽在:“汪子熙”:...

2020-11-26 17:23:48 26

原创 SAP Spartacus里的HTTPErrorInterceptor的单元测试设计原理

测试UnKnownErrorHandler是否能正确 处理UnknownError这个状态:这个handler是import进来的:调用经过TestBed.inject注入后的http:执行subscribe:UnknownErrorHandler此时才被惰性加载:这个fake的HTTP请求确实会触发我们自定义的http intercept:下面这行代码的语义是,确保有一个HTTP GET请求被发送:调用testModule的injector根据UnknownErrorHand

2020-11-26 17:05:15 25

原创 Angular如何对包含了HTTP请求的服务类进行单元测试

本文使用到的所有代码在Github这个文件夹下面:https://github.com/wangzixi-diablo/angular-sandbox/blob/master/src/app/ngrxdemo/service/unittest-study服务类实现:import { Injectable } from '@angular/core';import { HttpClient, HttpRequest } from '@angular/common/http';@Injectable

2020-11-26 15:48:58 28

原创 Spartacus里HTTPErrorInterceptor的设计原理

这个Interceptor继承自HttpInterceptor,在intercept方法里,理论上能监控所有的HTTP方法,只是在这个方法的实现体里,手动选择只CatchError:request对象:现在暂时还不知道这条next interceptor链是怎么build的。更多Jerry的原创文章,尽在:“汪子熙”:...

2020-11-26 15:23:21 23

原创 Angular应用的router-outlet使用一个例子

项目地址:https://angular-jerry-empty-store.stackblitz.ioTopBar Component里,使用Angular routerLink指令设置了一个路由参数/top:输入完整的url:https://angular-jerry-empty-store.stackblitz.io/top之后,界面如图:路由参数top自动从地址栏里消失了。App.component.html:里面定义了router-outlet:<app-top-bar&

2020-11-25 21:59:06 45

原创 Angular依赖注入的学习笔记

Angular官方文档Specifying a provider tokenIf you specify the service class as the provider token, the default behavior is for the injector to instantiate that class with new.In the following example, the Logger class provides a Logger instance.providers

2020-11-25 19:06:42 34

原创 NullInjectorError:No provider for MyNewService

错误消息:ERROR NullInjectorError: R3InjectorError(AppModule)[MyService -> MyNewService -> MyNewService -> MyNewService]:NullInjectorError: No provider for MyNewService!at NullInjector.get (http://localhost:4200/vendor.js:62758:27)at R3Injector.ge

2020-11-25 16:44:40 32

原创 SAP Spartacus避免不能向下兼容的breaking changes

文档地址以下这些都是引入了无法向下兼容的breaking changes,需要尽量避免:Changing the selector of a component, directive, or pipe. 更改了Component,directive或者pipe的selectorRemoving or changing the name of exported classes, functions, constants, interfaces or types in public_api.ts.修改

2020-11-25 15:55:46 27

原创 一个好用的查看Angular应用ngrx状态的Chrome扩展:Redux devTools

Redux DevTools:https://chrome.google.com/webstore/detail/lmhkpmbekcpmknklioeibfkpmmfibljd安装完毕后,在Chrome开发者工具里会多出一个Redux面板:以及在Chrome右上角的扩展工具栏里,会点亮Redux DevTools对应的图标。此时在redux面板里即可方便的查看ngrx相关的state和action:可以输入关键字进行过滤,比如查看和Currency加载相关的action:action

2020-11-22 21:18:28 39

原创 SAP Spartacus的发布方式以及语义化版本管理机制

Spartacus打包之后,以库的方式发布到npmjs.com上。Spartacus库主要有三个实体组成:core,Storefront和styles. 其中Storefront包含了用户肉眼可见的,组成Storefront外观的UI组件,客户可以重用和增强这些组件。Core则包含了Spartacus的控制逻辑,用户通过Angular依赖注入的机制,可以开发自己的服务类,然后注入到core框架之中。Styles包含了Spartacus的界面样式实现,客户可以对这些样式进行定制化,或者用自开发的样式来覆盖

2020-11-21 21:51:45 59

自己用Java编写的有道云笔记图片批量下载工具

使用方式:java -jar tool.jar [0,1,2] 0,1,2分别是有道云笔记的编号。0的guid:c91a710af51c1e1b20f5d1da2140a9e4; 1的guid:4cc557ab9b7cbde0515b49a155c5dce3 2的guid:6eaae532daaa678cc610f2a34cbc9119

2020-11-29

《Jerry 2017年的五一小长假:8种经典排序算法的ABAP实现》文章的源代码

《Jerry 2017年的五一小长假:8种经典排序算法的ABAP实现》文章的源代码下载,解压之后手动复制粘贴到ABAP系统的SE24或者SE80事物码里。

2020-11-24

汪子熙的留言板

发表于 2020-01-02 最后回复 2020-03-20

怎样才是理想的程序员

发表于 2015-06-28 最后回复 2019-07-29

SAP的这三款CRM解决方案,您能区分清楚么

发表于 2018-01-08 最后回复 2018-01-09

脑子快”的程序员更优秀吗

发表于 2015-08-09 最后回复 2015-10-27

一个平庸程序员的自白

发表于 2015-08-22 最后回复 2015-08-22

金庸小说里程序猿的练级心法

发表于 2015-06-28 最后回复 2015-08-14

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人 TA的粉丝

提示
确定要删除当前文章?
取消 删除