Skip to content

服务请求 IO

TIP

如果你已经了解了《必知必会 —— 服务请求 - createIO》》的内容,就可以跳过这部分。

功能

  • 将表操作、云函数调用、接口调用统一封装到 io 内,这样做的好处有
    • 抛弃 io.invoke('cloudFunctionName') 形式调用云函数,改为 io.faas.cloudFunctionName,减少魔法值的使用
    • 可以将云函数、api 归并到一起,避免在不同的地方进行对云函数、api 重复声明
  • 增加 typescript declaration,可以更加便捷高效地调用 io
    • image
  • 新增 IOError,所有的 io operation 执行错误时都会抛出统一的错误对象,方便错误收集上报以及错误信息提示

使用方法

createIO

js
import {createIO} from '@ifanrx/faas'

const io = createIO({
  // 知晓云数据表配置
  table: {
    // key 将作为该表在 io 中的引用名字,value 为该表在知晓云内表名
    userprofile: '_userprofile',
    settings: 'settings',
    likesLog: 'likes_log',
  },
  /**
   * 后端接口配置
   * api 若不配置 method,默认会使用 GET 发送请求
   * 通过 io.api.apiKey 调用
   */
  api: {
    getUserprofile: {
      method: 'POST',
      url: '/xxx',
    },
  },
  /**
   * 云函数配置
   * 通过 io.faas.faasKey 调用
   */
  faas: {
    helloWorld: 'hello_world',
  },
})

export default io

io 基础功能

example

js
// 构建知晓云 table 查询条件
// 更多可参考:https://doc.minapp.com/js-sdk/schema/frag/query.html
const query = io.query
query.compare('key', '=', 'something')

// 构建知晓云用户实例
// 更多可参考:https://doc.minapp.com/js-sdk/user.html
const user = io.user
user.get(userID)

// 构建知晓云文件实例
// 更多可参考:https://doc.minapp.com/js-sdk/file/
const file = io.file
file.upload()

// 构建知晓云 table 实例
// 更多可参考:https://doc.minapp.com/js-sdk/schema/
const table = new wx.BaaS.TableObject('_userprofile')
const record = table.create() // 本地创建一条空记录

// 上传单个文件到知晓云
const uploadTask = io.uploadFile(file, options)
uploadTask.onProgressUpdate(e => {
  // https://doc.minapp.com/js-sdk/file/file.html#监听上传进度变化事件和中断上传任务-仅限微信小程序
  console.log(e)
})

// 上传多个文件到知晓云
const uploadTask = io.uploadFiles(files, options)

知晓云数据表读写操作

example

js
// 根据 record id 获取对应记录
io.userprofile.get({id: 'xxx'})

// 根据查找条件找到记录列表
io.userprofile.find({query: io.query, limit: 20, offset: 0})

// 根据查找条件找到第一条满足条件的记录
io.userprofile.first({query: io.query})

// 已知记录 id,修改数据记录
io.userprofile.update({id: 'xxx', data: {name: 'xxx'}})

// 根据查找条件修改记录列表
io.userprofile.updateMany({query: io.query, data: {name: 'xxx'}})

// 已知记录 id,删除记录
io.userprofile.delete({id: 'xxx'})

// 根据查找条件删除记录列表
io.userprofile.deleteMany({query: io.query})

// 创建单条记录
io.userprofile.create({name: 'xxx'})

// 创建多条记录
io.userprofile.createMany([{name: '张三'}, {name: '李四'}])

// 获取满足当前查找条件的记录数量
io.userprofile.count({query: io.query})

// 获取当前数据表内所有数据项
io.userprofile.findAll()

get/find/first/update/updateMany/create 都拥有 plain 参数,当 plain 为 true 时,会将响应数据格式化,返回 response.data(find 操作是个另外,当 plain 为 true 时会返回 response.data.objects),当 plain 为 false 时,则会将完整的 response 返回。plain 默认值都是 true

云函数调用

云函数的调用是对知晓云 sdk 的 BaaS.invoke 进行封装,省略了调用 invoke 时对 functionName 参数的传入,让云函数的调用更加便捷,同时支持代码提示
此处云函数调用的封装对云函数的响应内容进行简单处理,当云函数响应的 code 为 0 时(此时云函数执行成功),会只返回云函数响应结构中的 data 字段,否则会抛出 IOError

类型定义

ts
faas: {
  [P in keyof T]: <
    TRequestPayload extends RequestPayload = RequestPayload,
    TSync extends boolean = true
  >(
    payload?: TRequestPayload,
    sync?: TSync
  ) => IOPromise<CloudFunctionResponse<TSync>>
}
  • payload 为请求云函数参数,sync 表示是否以同步的形式调用云函数
  • 若以同步的方式执行云函数,该方法会在云函数执行完成后返回
  • 若以异步的方式执行云函数,云函数会立刻返回 {status: "ok"},且无法获取云函数的执行结果
  • 同步与异步云函数有不同的超时时间,同步云函数为 5 秒,而异步云函数为 5 分钟
  • 默认使用同步的形式调用云函数
  • 更多内容请查阅文档 BaaS.invoke

example

js
const io = createIO({
  faas: {
    helloWorld: 'hello_world',
  },
})

// 默认使用同步的形式调用云函数
io.faas.helloWorld({message: 'hello world'})

// 使用异步的形式调用云函数
io.faas.helloWorld({message: 'hello world'}, false).then(console.log) // {status: 'ok'}

后端接口调用

一般来说,在微信小程序内请求后端接口都需要依赖知晓云 sdk 的 BaaS.request,使用用户在知晓云登录获取的 token 来完成鉴权
对后端接口请求的封装主要是省去在调用接口时传入请求 url 和 method 步骤,支持与云函数一致的调用方式,同样支持代码提示
需要注意的是,在调用 createIO 配置 api 时,需要传入该请求对应的 request method,不传默认使用 GET 请求。并且只能用来处理内部的 api,内部 api 有统一的响应结构

ts
{
  status: string // 取值有 ok | error
  error_code: integer, // 错误状态码
  error_msg: string // 底层的错误信息
  display_error_msg: string // 前端显示的错误信息
  data: {} // 正常数据
}

当 status 为 error 时,抛出 IOError,否则返回 data

类型定义

ts
declare type ApiMethod =
  | 'GET'
  | 'OPTIONS'
  | 'HEAD'
  | 'POST'
  | 'PUT'
  | 'DELETE'
  | 'TRACE'
  | 'CONNECT'

declare interface ApiConfig {
  method?: ApiMethod
  url: string
}

declare type Api = Record<string, ApiConfig>

declare interface ApiRequestOptions {
  header?: object
  dataType?: string
}

declare interface ApiOperation<T extends Api> {
  api: {
    [P in keyof T]: (
      payload?: RequestPayload,
      options?: ApiRequestOptions
    ) => IOPromise<ApiResponse>
  }
}

example

js
const io = createIO({
  api: {
    getUserprofile: {
      method: 'POST',
      url: '/xxxx',
    },
  },
})

io.api.getUserprofile({message: 'hello world'}, {header: {xxx: 'xxx'}})

IOError

io 内所有方法执行出错时,都会抛出 IOError,方便统一错误处理以及错误上报

类型定义

js
class IOError extends Error {
  code: number
  displayMessage: string
  info: Record<string, any>
}

TIP

通常情况下,小程序端可以配合 message.showIOErrorModal 使用,以便轻松地将错误信息显示给用户。

js
try {
  // 调用 io 方法
} catch (error) {
  message.showIOErrorModal(error, {
    10001: '优先显示自定义报错',
    'request timeout': '网络超时',
    default: '当最终文案为空时,使用该默认回退文案',
  })
}