4.2.4 框架之网络请求-HttpClient

oinone提供统一的网络请求底座,基于graphql二次封装

一、初始化

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();
http.setMiddleware() // 必须设置,请求回调。具体查看文章https://shushi.yuque.com/yqitvf/oinone/vwo80g
http.setBaseURL() // 必须设置,后端请求的路径

图4-2-4-1 初始化代码示例

二、HttpClient详细介绍

获取实例

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();

图4-2-4-2 获取实例

接口地址

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();
http.setBaseURL('接口地址');
http.getBaseURL(); // 获取接口地址

图4-2-4-3 接口地址

请求头

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();
http.setHeader({key: value});

图4-2-4-4 请求头

variables

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();
http.setExtendVariables((moduleName: string) => {
 return customFuntion();

});

图4-2-4-5 variables

回调

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();
http.setMiddleware([middleware]);

图4-2-4-6 回调

业务使用-query

private http = HttpClient.getInstance();
private getTestQuery = async () => {
 const query = `gql str`;
 const result = await this.http.query('module name', query);
 console.log(result)
 return result.data[`xx`]['xx']; // 返回的接口,打印出result对象层次返回
};

图4-2-4-7 业务使用-query

业务使用-mutate

private http = HttpClient.getInstance();

private getTestMutate = async () => {
  const mutation = `gql str`;

  const result = await this.http.mutate('module name', mutation);
    console.log(result)
  return result.data[`xx`]['xx']; // 返回的接口,打印出result对象层次返回
};

图4-2-4-8 业务使用-mutate

三、如何使用HttpClient

初始化

在项目目录src/main.ts下初始化httpClient

初始化必须要做的事:

  • 设置服务接口链接

  • 设置接口请求回调

业务实战

前文说到自定义新增宠物表单,让我们在这个基础上加入我们的httpClient;

第一步新增service.ts

image.png

图4-2-4-8 新增service.ts

service.ts

import { HttpClient } from '@kunlun/dependencies';

const addPetMutate = async (modelName, data) => {
    const http = HttpClient.getInstance();
    const mutateGql = `mutation{
    petMutation{
      addPet(data:${data})
       {
        id
      }
    }
  }`;

    const result = await http.mutate('pet', mutateGql);
    return (result as any).data['petMutation']['addPet'];
};

export { addPetMutate };

图4-2-4-9 service.ts

第二步业务中使用

import { constructOne, queryOne, SPI, ViewWidget, Widget, IModel, getModelByUrl, getModel, getIdByUrl, FormWidgetV3, CustomWidget, CallChaining } from '@kunlun/dependencies';
import PetFormView from './PetFormView.vue';
// 引入
import { addPetMutate } from './service';

@SPI.ClassFactory(CustomWidget.Token({ widget: 'PetForm' }))
export class PetFormViewWidget extends FormWidgetV3 {
  public initialize(props) {
    super.initialize(props);
    this.setComponent(PetFormView);
    return this;
  }

  /**
   * 数据提交
   * @protected
   */
  @Widget.Reactive()
  @Widget.Inject()
  protected callChaining: CallChaining | undefined;

  private modelInstance!: IModel;

  /**
   * 重要!!!!
   * 当字段改变时修改formData
   * */
  @Widget.Method()
  public onFieldChange(fieldName: string, value) {
    this.setDataByKey(fieldName, value);
  }

  /**
   * 表单编辑时查询数据
   * */
  public async fetchData(content: Record<string, unknown>[] = [], options: Record<string, unknown> = {}, variables: Record<string, unknown> = {}) {
    this.setBusy(true);
    const context: typeof options = { sourceModel: this.modelInstance.model, ...options };
    const fields = this.modelInstance?.modelFields;
    try {
      const id = getIdByUrl();
      const data = (await queryOne(this.modelInstance.model, (content[0] || { id }) as Record<string, string>, fields, variables, context)) as Record<string, unknown>;

      this.loadData(data);
      this.setBusy(false);
      return data;
    } catch (e) {
      console.error(e);
    } finally {
      this.setBusy(false);
    }
  }

  /**
   * 新增数据时获取表单默认值
   * */
  @Widget.Method()
  public async constructData(content: Record<string, unknown>[] = [], options: Record<string, unknown> = {}, variables: Record<string, unknown> = {}) {
    this.setBusy(true);
    const context: typeof options = { sourceModel: this.modelInstance.model, ...options };
    const fields = this.modelInstance.modelFields;
    const reqData = content[0] || {};
    const data = await constructOne(this.modelInstance!.model, reqData, fields, variables, context);
    return data as Record<string, unknown>;
  }

  @Widget.Method()
  private async reloadData() {
    const data = await this.constructData();
    // 覆盖formData
    this.setData(data);
  }

  @Widget.Method()
  public onChange(name, value) {
    this.formData[name] = value;
  }

  protected async mounted() {
    super.mounted();
    const modelModel = getModelByUrl();
    this.modelInstance = await getModel(modelModel);
    this.fetchData();
    // 数据提交钩子函数!!!
    this.callChaining?.callBefore(() => {
      return this.formData;
    });
  }

  @Widget.Method()
  private async addPet() {
    // 调用
    const data = await addPetMutate('petModule', this.getData());
  }
}

图4-2-4-10 业务中使用

Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9305.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
史, 昂's avatar史, 昂数式管理员
Previous 2024年5月23日 am8:33
Next 2024年5月23日 am8:35

相关推荐

  • 第3章 Oinone的基础入门

    本章主要介绍如何快速入门,了解如何在Oinone上进行开发。我们将通过准备环境、构建自己的第一个Oinone模块、完成一些小功能等方式来全面了解Oinone,这将是一个很好的开始。 具体来说,本章包括以下几个方面: 环境搭建:准备Windows或Mac版环境。 Oinone以模块为组织:了解Oinone模块的概念和如何创建和使用模块。 Oinone以模型为驱动:了解Oinone模型的概念和如何使用模型来构建应用。 Oinone以函数为内在:了解Oinone函数的概念和如何使用函数来实现应用逻辑。 Oinone以交互为外在:了解Oinone交互的概念和如何使用交互来设计和实现应用界面。

    Oinone 7天入门到精通 2024年5月23日
    2.9K00
  • 数据类

    1.数据类 1.1 新增数据 新增数据节点可以为任意模型通过表达式新增数据,包含两种模式,「节点执行完即增加业务数据」功能下新增的数据也可以同步触发流程,相反「节点执行完不增加业务数据」则不会触发新增业务数据关联的流程,数据仅可用于后续流程使用。 流程增加的数据在节点执行时就生效。 1.2 更新数据 更新数据节点可以为任意模型通过表达式更新数据。 1.3 获取数据 当流程需要调用触发模型之外的模型中的数据时就需要使用获取数据的功能。 需要选择获取单条/多条数据,选择一个获取数据的模型,可以设置一些筛选项减少不必要的数据。最后需要设置未获取到数据时的执行方式。 继续执行:跳过本次数据获取,继续执行流程。 向模型中新增数据后继续执行:新增数据来供后续节点使用,新增数据同时存入数据库中。 终止流程:终止流程将结束该流程,不管之后是否还有流程节点。 1.4 删除数据 删除数据节点可以将流程节点上面的模型数据从数据库中删除。 1.5 更新流程参数 可以将「流程配置」中的「流程参数」进行修改,仅有变更过的流程参数才能其他节点选中。 1.6 引用逻辑 可以在流程中使用模块自带的逻辑或使用低代码设计的逻辑。

    2024年5月23日
    2.0K00
  • 4.1.8 函数之事务管理

    一、事务管理介绍 函数Function支持事务字段为isTransaction(默认为false),事务传播行为propagationBehavior(默认PROPAGATION_SUPPORTS),事务隔离级别isolationLevel(默认使用数据库默认的事务隔离级别),所以不会默认为函数添加事务。另外事务配置提供全局配置。 平台事务管理兼容Spring声明式与编程式事务,支持多数据源事务管理。事务管理中多数据源嵌套独立事务,不会造成死锁风险。使用多数据源或分表操作,不会导致脏读。如果需要多数据源分布式事务,请使用PamirsTransational分布式事务管理方案(@PamirsTransational(enableXa=true))。分布式事务一般用于量小的跨模块配置管理场景 使用方式 声明式事务,使用@PamirsTransactional注解在需要事务管理的类或方法上标注。在非无代码场景下,与@Transactional注解功能一致。 编程式事务,使用PamirsTransactionTemplate即可。在非无代码场景下,与TransactionTemplate功能一致。 配置式事务,使用TxConfig模型在模块安装时初始化存储事务配置数据。 事务特性 原子性 (atomicity):强调事务的不可分割. 一致性 (consistency):事务的执行的前后数据的完整性保持一致. 隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰 持久性(durability) :事务一旦结束,数据就持久到数据库 事务隔离级别 事务隔离级别指的是一个事务对数据的修改与另一个并行的事务的隔离程度,当多个事务同时访问相同数据时,如果没有采取必要的隔离机制,就可能发生以下问题: 问题 描述 脏读 一个事务读到另一个事务未提交的更新数据,所谓脏读,就是指事务A读到了事务B还没有提交的数据,比如银行取钱,事务A开启事务,此时切换到事务B,事务B开启事务–>取走100元,此时切换回事务A,事务A读取的肯定是数据库里面的原始数据,因为事务B取走了100块钱,并没有提交,数据库里面的账务余额肯定还是原始余额,这就是脏读 不可重复读 在一个事务里面的操作中发现了未被操作的数据 比方说在同一个事务中先后执行两条一模一样的select语句,期间在此次事务中没有执行过任何DDL语句,但先后得到的结果不一致,这就是不可重复读 幻读 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象 发生了幻觉一样。 表4-1-8-1 事务隔离级别 Pamirs(Spring)支持的隔离级别 隔离级别 描述 DEFAULT 使用数据库本身使用的隔离级别 ORACLE(读已提交) MySQL(可重复读) READ_UNCOMITTED 读未提交(脏读)最低的隔离级别,一切皆有可能。 READ_COMMITED 读已提交,ORACLE默认隔离级别,有不可重复读以及幻读风险。 REPEATABLE_READ 可重复读,解决不可重复读的隔离级别,但还是有幻读风险。 SERLALIZABLE 串行化,最高的事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务,这样就解决了脏读、不可重复读和幻读的问题了 表4-1-8-2 隔离级别与描述 隔离级别 脏读可能性 不可重复读可能性 幻读可能性 加锁度 READ_UNCOMITTED 是 是 是 否 READ_COMMITED 否 是 是 否 REPEATABLE_READ 否 否 是 否 SERLALIZABLE 否 否 否 是 表4-1-8-3 隔离级别说明表 事务的传播行为 保证同一个事务中 PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认) PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务 PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常 保证没有在同一个事务中 PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务 PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务 PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常 PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行 A中嵌套B事务,嵌套PROPAGATION_REQUIRES_NEW方法勿与A在同类中。 异常状态 PROPAGATION_REQUIRES_NEW (两个独立事务) PROPAGATION_NESTED (B的事务嵌套在A的事务中) PROPAGATION_REQUIRED (同一个事务) A抛异常 B正常 A回滚,B正常提交 A与B一起回滚 A与B一起回滚 A正常 B抛异常 1.如果A中捕获B的异常,并没有继续向上抛异常,则B先回滚,A再正常提交; 2.如果A未捕获B的异常,默认则会将B的异常向上抛,则B先回滚,A再回滚 B先回滚,A再正常提交 A与B一起回滚 A抛异常B抛异常 B先回滚,A再回滚 A与B一起回滚 A与B一起回滚 A正常 B正常 B先提交,A再提交 A与B一起提交 A与B一起提交 表4-1-8-4 事务传播行为 二、声明式事务(举例) Step1 修改PetShopBatchUpdateAction 用@PamirsTransactional或者@Transactional注解来声明事务,PamirsTransactional跟Spring的Transactional区别在于PamirsTransactional支持多库事务,但此多库事务为非严格的分布式多库事务,之所以选择这个方案,原因如下 a. 不损害任何性能。 b. 事务保障率超过4个9 c. 经过阿里的大厂验证,特别是在阿里的结算平台中得到了很好的验证 @PamirsTransactional更多配置项请详见4.1.7【函数之元数据详解】一文,自己多试试。同时@PamirsTransactional百分百兼容@Transactional @Action(displayName = "确定",bindingType = ViewTypeEnum.FORM,contextType = ActionContextTypeEnum.SINGLE) @PamirsTransactional //@Transactional public PetShopBatchUpdate conform(PetShopBatchUpdate data){ if(data.getPetShopList() == null || data.getPetShopList().size()==0){ throw PamirsException.construct(DemoExpEnumerate.PET_SHOP_BATCH_UPDATE_SHOPLIST_IS_NULL).errThrow(); } List<PetShopProxy> proxyList = data.getPetShopList(); for(PetShopProxy petShopProxy:proxyList){ petShopProxy.setDataStatus(data.getDataStatus()); } new PetShopProxy().updateBatch(proxyList); throw PamirsException.construct(DemoExpEnumerate.SYSTEM_ERROR).errThrow(); // return data; } 图4-1-8-1 修改PetShopBatchUpdateAction Step2 重启看效果 进入店铺管理列表页,选择记录点击【批量更新数据状态】按钮,修改记录的数据状态为【未启用】,提交看效果。期望效果为:提示系统异常,数据修改失败 图4-1-8-2 数据状态显示已启用 图4-1-8-3 批量更新数据状态…

    2024年5月23日
    1.5K00
  • 3.2 Oinone以模块为组织

    模块(module):是按业务领域划分和管理的最小单元,是一组功能、界面的集合。 带大家快速认识下如何构建一个oinone的模块并启动它。我会从以下几个维度去介绍模块的构建与启动方式、模块详解。让大家直观且全方位地了解oinone的模块所包含的内容 构建第一个Module 启动前端工程 应用中心

    Oinone 7天入门到精通 2024年5月23日
    2.7K00
  • 5.6 商业支撑之商品域

    一、基础介绍 当业务在线化后,用于内部管理的产品主数据,叠加一堆销售属性变成了商品被推倒了前台,成为导购链路中最最重要的信息载体。看似最基础和最简单的商品模块也有很多门道。主要集中在以下几个方面: 商品的属性如何管理、呈现、参与导购(类目、搜索的过滤条件) 如何解决固定不变的内部管理需求与基于销售特性长期变化的运营需求之间的矛盾 在多渠道情况渠道商品,如何映射到实际sku进行履约 二、模型介绍 图5-6-1 模型介绍 类目属性,解决“商品的属性如何管理、呈现、参与导购(类目、搜索的过滤条件)” 前后台类目设计,解决“如何解决固定不变的内部管理需求与基于销售特性长期变化的运营需求之间的矛盾” 销售Sku和库存Sku设计,解决“在多渠道情况渠道商品,如何映射到实际sku进行履约” 要把这些问题搞清楚,得先把名词统一下: 领域 名称 oinone的定义 说明 举例 平台运营视角 Spu Product –>Spu2.1.9 –> 3.0.0 SPU(Standard Product Unit):标准化产品单元。SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性 iPhone X可以确定一个产品 后台类目 后台类目(Category) 商品分类分级管理,以及规范该类目下公共属性可以分为普通属性、销售属性 比如类目:3c数码/手机销售属性:内存大小、颜色等普通属性:分辨率 前台类目 前台类目(FrontCategory) 平台导购类目 通过前台类目关联后台类目或后台类目属性,用于满足运营需求 大体上SPU处于最上层、Item属于下一级,而SKU属于最低一层。SPU是平台层面,Item是商家层面,SKU是商家的Item确定销售属性SPU非必须,在平台类交易中,平台方为了规范商家发布商品信息,进行统一运营时需要 商家销售视角 Item 渠道商品(Item) 简单来说是:SPU加上归属商家、以及商家自有的价格与描述 商家A的iPhone X Sku 销售Sku(SaleSku) SKU=Stock Keeping Unit(库存保有单位)。是对每一个产品和服务的唯一标示符,该系统的使用SKU的值根于数据管理,使公司能够跟踪系统,如仓库和零售商店或产品的库存情况。 iPhone X 64G 银色 则是一个SKU。 店铺类目 ShopCategory 商家店铺导购类目 在平台类电商,商家都会有自己独立的店铺主页,商家类目跟前台类目作用类似,只是局限影响范围为商家店铺内 销售SKU中会有一个InvSkuCode来关联InventorySku,比如:品牌上在不同渠道(淘宝、京东、自建电商)中会有不同的销售SKU,在从渠道同步销售SKU会根据外部code 商家管理视角 产品或库存Sku InventorySku 跟销售领域的sku的定义类似,但销售领域是为了规范购买行为,这里规范企业内部管理。 iPhone X 64G 银色 组合Sku InventorySkuComposition 空调有内外机组合而成,这就是一个组合sku 产品分类 ProductKind 企业内部管理划分 商品系列 ItemSeries 指互相关联或相似的产品,是按照一定的分类标准对企业生产经营的全部产品进行划分的结果。一个产品系列内往往包括多个产品项目。产品系列的划分标准有产品功能、消费上的连带性、面向的顾客群、分销渠道、价格范围等 存货类别 StorageKind 为了反映存货的组成内容,正确计算产品的生产成本以及销售成本,会计上必须对存货进行科学地分类,按存货的不同类别进行核算 表5-6-1 各领域名称说明

    2024年5月23日
    2.2K00

Leave a Reply

Please Login to Comment