HarmonyOS 鸿蒙学习笔记2-网络请求、端云一体化

一、网络请求

1、HTTP数据请求

应用通过`HTTP`发起一个数据请求,支持常见的`GET`、`POST`、`OPTIONS`、`HEAD`、`PUT`、`DELETE`、`TRACE`、`CONNECT`方式。

约束与限制

使用网络管理模块的相关功能时,需要请求相应的权限。

| 权限名 | 说明 |

| ------ | ------ |

| ohos.permission.GET_NETWORK_INFO | 获取网络连接信息。 |

| ohos.permission.SET_NETWORK_INFO | 修改网络连接状态。 |

| ohos.permission.INTERNET | 允许程序打开网络套接字,进行网络连接。 |

使用`Stage`模型的应用,在`module.json5`配置文件中声明权限:

```js

{

  "module" : {

    // ...

    "requestPermissions":[

      {

        "name" : "ohos.permission.INTERNET",

        "reason": "描述申请权限的原因"

      }

    ]

  }

}

```

[权限详细属性配置](https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/accesstoken-guidelines-0000001493744016-V3)

http模块

`HTTP`数据请求功能主要由`http`模块提供,涉及的接口如下表,具体的接口说明参考[API文档](https://developer.harmonyos.com/cn/docs/documentation/doc-references-V3/js-apis-http-0000001478061929-V3)。

| 接口名 | 功能描述 |

| ------ | ------ |

| createHttp() | 创建一个http请求。 |

| request() | 根据URL地址,发起HTTP网络请求。 |

| destroy() | 中断请求任务。 |

| on(type: 'headersReceive') | 订阅HTTP Response Header 事件。 |

| off(type: 'headersReceive') | 取消订阅HTTP Response Header 事件。 |

| once(type: 'headersReceive') | 订阅HTTP Response Header 事件,但是只触发一次。 |

request接口开发步骤

1. 从`@ohos.net.http`中导入`http`模块。

2. 调用`createHttp()`方法,创建一个`HttpRequest`对象。

3. 调用该对象的`on()`方法,订阅`http`响应头事件,此接口会比`request`请求先返回。可以根据业务需要订阅此消息。

4. 调用该对象的`request()`方法,传入`http`请求的`url`地址和可选参数,发起网络请求。

5. 按照实际业务需要,解析返回结果。

6. 调用该对象的`off()`方法,取消订阅`http`响应头事件。

7. 当该请求使用完毕时,调用`destroy()`方法主动销毁。

```js

// 引入包名

import http from '@ohos.net.http';



// 每一个httpRequest对应一个HTTP请求任务,不可复用

let httpRequest = http.createHttp();

// 用于订阅HTTP响应头,此接口会比request请求先返回。可以根据业务需要订阅此消息

// 从API 8开始,使用on('headersReceive', Callback)替代on('headerReceive', AsyncCallback)。 8+

httpRequest.on('headersReceive', (header) => {

    console.info('header: ' + JSON.stringify(header));

});

httpRequest.request(

    // 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定

    "EXAMPLE_URL",

    {

        method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET

        // 开发者根据自身业务需要添加header字段

        header: {

            'Content-Type': 'application/json'

        },

        // 当使用POST请求时此字段用于传递内容

        extraData: {

            "data": "data to send",

        },

        expectDataType: http.HttpDataType.STRING, // 可选,指定返回数据的类型

        usingCache: true, // 可选,默认为true

        priority: 1, // 可选,默认为1

        connectTimeout: 60000, // 可选,默认为60000ms

        readTimeout: 60000, // 可选,默认为60000ms

        usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定

    }, (err, data) => {

        if (!err) {

            // data.result为HTTP响应内容,可根据业务需要进行解析

            console.info('Result:' + JSON.stringify(data.result));

            console.info('code:' + JSON.stringify(data.responseCode));

            // data.header为HTTP响应头,可根据业务需要进行解析

            console.info('header:' + JSON.stringify(data.header));

            console.info('cookies:' + JSON.stringify(data.cookies)); // 8+

        } else {

            console.info('error:' + JSON.stringify(err));

            // 取消订阅HTTP响应头事件

            httpRequest.off('headersReceive');

            // 当该请求使用完毕时,调用destroy方法主动销毁

            httpRequest.destroy();

        }

    }

);

```

2、应用文件的上传和下载

用户文件的上传和下载

> 在开发过程中,避免不了要去上传下载一些文件,如上传头像、保存图片、保存音频等。

上传

首先用户需要选择文件,这里需要用到`@ohos.file.picker`模块,选择之后会得到一个`uri`本地文件地址,以图片选择为例:

```js

import picker from '@ohos.file.picker';

@Entry

@Component

struct Picker {

  @State url:string=""

  build() {

    Row() {

      Column() {

        if(this.url){

          Image(this.url)

            .width("100%")

        }

        Text("选择图片")

          .textAlign(TextAlign.Center)

          .lineHeight(80)

          .onClick(async()=>{

            // 创建picker实例

            let photoPicker = new picker.PhotoViewPicker();

            // 通过选择模式拉起photoPicker界面,用户可以选择一个或多个图片/视频。

            let result = await photoPicker.select()

            // photoUris为选择的图片uri集合

            this.url = result.photoUris[0]

          })

      }

      .width('100%')

    }

    .height('100%')

  }

}

```

执行上传操作:

```js

import picker from '@ohos.file.picker';

import request from '@ohos.request';

import common from '@ohos.app.ability.common';

import fs from '@ohos.file.fs';

@Entry

@Component

struct Picker {

  @State url:string="";

  private context = getContext(this) as common.UIAbilityContext;

  build() {

    Row() {

      Column() {

        if(this.url){

          Image(this.url)

            .width("100%")

        }

        Text("选择图片")

          .textAlign(TextAlign.Center)

          .lineHeight(80)

          .onClick(async()=>{

            // 创建picker实例

            let photoPicker = new picker.PhotoViewPicker();

            // 通过选择模式拉起photoPicker界面,用户可以选择一个或多个图片/视频。

            let result = await photoPicker.select()

            // photoUris为选择的图片uri集合

            this.url = result.photoUris[0];

            // 将文件拷贝至cache目录,目前request.uploadFile只能上传cache目录下的文件 需要用到fs模块

            let cacheDir = this.context.cacheDir;//获取缓存目录平台绝对路径

            let imgName = this.url.split('/').pop()+".jpg";

            let dstPath = cacheDir + '/' + imgName;//目标地址

            let srcFile = fs.openSync(this.url);//选择的文件

            let dstFile = fs.openSync(dstPath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);//目标文件

            fs.copyFileSync(srcFile.fd, dstFile.fd);//拷贝

            fs.closeSync(srcFile);//关闭文件访问

            fs.closeSync(dstFile);//关闭文件访问

            // 上传请求配置信息

            let uploadConfig = {

              url: 'http://xxx.com/upload_file', //需要手动替换为真实服务器地址

              method: "POST",

              // name为上传文件的参数名

              files: [{ filename: imgName, name: "file", uri: 'internal://cache/' + imgName, type: "jpg" }],

              header:{},

              // 携带额外字段

              data:[

                // { name: 'name', value: 'value' }

              ]

            };

            try{

              let uploadTask = await request.uploadFile(this.context,uploadConfig);

              uploadTask.on('complete', (taskStates) => {

                // 上传完毕,不会返回响应结果,可以生成唯一标识,后端提供接口 获取上传地址

                console.info(`----upload complete taskState: ${JSON.stringify(taskStates)}`);

                // 删除拷贝的文件

                fs.unlink(dstPath)

              });

            }

            catch(err){

              console.log(JSON.stringify(err),"--------------------")

            }

          })

      }

      .width('100%')

    }

    .height('100%')

  }

}

```

下载

```js

import common from '@ohos.app.ability.common';

import fs from '@ohos.file.fs';

import request from '@ohos.request';



// 获取应用文件路径

let context = getContext(this) as common.UIAbilityContext;

let filesDir = context.filesDir;



request.downloadFile(context, {

  url: 'http://www.mobiletrain.org/images/index/new_logo.png',//资源在线地址

  filePath: filesDir + '/new_logo.png'//本地存储地址

}).then((downloadTask) => {

  console.log("----------------------------------")

  downloadTask.on('complete', () => {

    // 需要拼接"file://"前缀 才能在页面中访问

    this.url = "file://"+filesDir + '/new_logo.png'

    console.log("下载完毕",this.url)

  })

}).catch((err) => {

  console.log(`下载失败, code: ${err.code}, message: ${err.message}`);

});

```

3、使用Axios

Axios

> `Axios` ,是一个基于 `promise` 的网络请求库,可以运行 `node.js` 和浏览器中。本库基于`Axios` 原库`v1.3.4`版本进行适配,使其可以运行在 `OpenHarmony`,并沿用其现有用法和特性。

- `http` 请求

- `Promise API`

- `request` 和 `response` 拦截器

- 转换 `request `和 `response` 的 `data` 数据

- 自动转换 `JSON data` 数据

下载安装

```

ohpm install @ohos/axios

```

接口和属性列表

| 接口 | 参数 | 功能 |

| ------ | ------ | ------ |

| axios(config) | config:请求配置 | 发送请求 |

| axios.create(config) | config:请求配置 | 创建实例 |

| axios.request(config) | config:请求配置 | 发送请求 |

| axios.get(url[, config]) | url:请求地址<br/>config:请求配置 | 发送get请求 |

| axios.delete(url[, config]) | url:请求地址<br/>config:请求配置 | 发送delete请求 |

| axios.post(url[, config]) | url:请求地址<br/>data:发送请求体数据<br/>config:请求配置 | 发送post请求 |

| axios.put(config) | url:请求地址<br/>data:发送请求体数据<br/>config:请求配置 | 发送put请求 |

| 属性 | 描述 |

| ------ | ------ |

| axios.defaults['xxx'] | 默认设置值,为请求配置 config 中的配置项</br>例如 axios.defaults.headers 获取头部信息 |

| axios.interceptors | 拦截器 |

请求配置

上传和下载和web端的axios有些差异,其他基本一致。

```js

{

  // `url` 是用于请求的服务器 URL

  url: '/user',



  // `method` 是创建请求时使用的方法 支持post/get/put/delete方法,不区分大小写,默认为get方法

  method: 'get', // default



  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。

  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL

  baseURL: 'https://www.xxx.com/info',



  // `transformRequest` 允许在向服务器发送前,修改请求数据

  // 它只能用于 'PUT', 'POST' 和 'PATCH' 这几个请求方法

  // 数组中最后一个函数必须返回一个字符串, 一个Buffer实例,ArrayBuffer,FormData,或 Stream

  // 你可以修改请求头。

  transformRequest: [function (data, headers) {

    // 对发送的 data 进行任意转换处理

    return data;

  }],



  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据

  transformResponse: [function (data) {

    // 对接收的 data 进行任意转换处理

    return data;

  }],



  // `headers` 是即将被发送的自定义请求头

  headers: {'Content-Type': 'application/json'},



  // `params` 是即将与请求一起发送的 URL 参数

  // 必须是一个无格式对象(plain object),其他对象如 URLSearchParams ,必须使用 paramsSerializer 进行序列化

  params: {

    ID: 12345

  },



  // `paramsSerializer` 是一个负责 `params` 序列化的函数

  paramsSerializer: function(params) {

    return params

  },



  // `data` 是作为请求主体被发送的数据

  // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'

  // 在没有设置 `transformRequest` 时,必须是以下类型之一,其他类型使用 transformRequest 转换处理

  // - string, plain object, ArrayBuffer

  data: {

    firstName: 'Fred'

  },



  // 发送请求体数据的可选语法

  // 请求方式 post

  // 只有 value 会被发送,key 则不会

  data: 'Country=Brasil&City=Belo Horizonte',



  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)

  // 如果请求超过 `timeout` 的时间,请求将被中断

  timeout: 1000,



  // `adapter` 允许自定义处理请求,这使测试更加容易。

  // 返回一个 promise 并提供一个有效的响应 (参见 lib/adapters/README.md)。

  adapter: function (config) {

    /* ... */

  },

  // 如果设置了此参数,系统将使用用户指定路径的CA证书,(开发者需保证该路径下CA证书的可访问性),否则将使用系统预设CA证书,系统预设CA证书位置:/etc/ssl/certs/cacert.pem。证书路径为沙箱映射路径(开发者可通过Global.getContext().filesDir获取应用沙箱路径)。目前仅支持后缀名为.pem的文本格式证书。

  caPath: '',



  // 优先级,范围[1,1000],默认是1,值越大,优先级越高;

  priority: 1,



  //  `responseType` 指定返回数据的类型,默认无此字段。如果设置了此参数,系统将优先返回指定的类型。

  // 选项包括: string:字符串类型; object:对象类型; array_buffer:二进制数组类型。

  responseType: 'string',



  // `onUploadProgress` 允许为上传处理进度事件,上传文件必须设置该事件

  onUploadProgress: function (progressEvent) {

    // 对原生进度事件的处理

  },



  // `onDownloadProgress` 允许为下载处理进度事件,下载文件必须设置该事件

  onDownloadProgress: function (progressEvent) {

    // 对原生进度事件的处理

  },



  // 基于应用程序的上下文,只适用于上传/下载请求

  context: context,



  // 下载路径。此参数,只适用于下载请求,

  // Stage模型下使用AbilityContext 类获取文件路径,比如:'${getContext(this).cacheDir}/test.txt’并将文件存储在此路径下

  filePath: context,

}

```

使用示例

```js

import axios from '@ohos/axios'

axios.get("http://xxxx").then(({data})=>{

  console.log(data)

})

```

上传文件

```js

import axios from '@ohos/axios'

import { FormData } from '@ohos/axios'



let formData = new FormData()

formData.append('file', 'internal://cache/blue.jpg')

// 发送请求

axios.post('https://www.xxx.com/upload', formData, {

  headers: { 'Content-Type': 'multipart/form-data' },

  context: getContext(this),

  onUploadProgress: (progressEvent) => {

    console.info(progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');

  },

}).then((res) => {

  console.info("result" + JSON.stringify(res.data));

}).catch((err) => {

  console.error("error:" + JSON.stringify(err));

})

```

下载文件

设置下载路径`filePath`(默认在'`internal://cache/`'路径下)。

关于`filePath`:

- filePath:'workspace/test.txt':默认路径下创建workspace路径,并将文件存储在workspace路径下。

- filePath:'test.txt':将文件存储在默认路径下。

- filePath:'workspace/':默认路径下创建workspace路径,并将文件存储在workspace路径下。

```js

let filePath = getContext(this).cacheDir + '/blue.jpg'

// 下载。如果文件已存在,则先删除文件。

try {

  fs.accessSync(filePath);

  fs.unlinkSync(filePath);

} catch(err) {}



axios({

  url: 'https://www.xxx.com/blue.jpg',

  method: 'get',

  context: getContext(this),

  filePath: filePath ,

  onDownloadProgress: (progressEvent): void => {

    console.info("progress: " + progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) : 0)

  }

}).then((res)=>{

  console.info("result: " + JSON.stringify(res.data));

}).catch((error)=>{

  console.error("error:" + JSON.stringify(error));

})

```

二、端云一体化

1、端云项目搭建

> 为丰富HarmonyOS对云端开发的支持、实现端云联动,DevEco Studio推出了云开发功能,开发者在创建工程时选择云开发模板,即可在DevEco Studio内同时完成HarmonyOS应用/元服务的端侧与云侧开发,体验端云一体化协同开发。

相比于传统开发模式,云开发模式具备成本低、效率高、门槛低等优势:

| 区别点   | 传统开发模式                                                 | 云开发模式                                           

| 开发工具 | 端侧与云侧各需一套开发工具,云侧需自建服务器,工具成本高。  |

| DevEco Studio一套开发工具即可支撑端侧与云侧同时开发,无需搭建服务器,工具成本低。 |

| 开发人员 | 端侧与云侧要求不同的开发语言,技能要求高。需多人投入,且开发人员之间需持续、准确沟通,人力与沟通成本高、效率低。 | 依托AppGallery Connect(以下简称AGC)Serverless云服务开放的接口,端侧开发人员也能轻松开发云侧代码,大大降低开发门槛。开发人员数量少,降低人力成本,提高沟通效率。 |

| 运维     | 需自行构建运营与运维能力,成本高、负担重。|         

| 直接接入AGC Serverless云服务,实现免运维,无运维成本或资源浪费。 |

搭建项目

1.登录[AppGallery Connect]

(https://developer.huawei.com/consumer/cn/service/josp/agc/index.html#/) 创建应用

点击我的项目,在项目页面中添加项目

若项目中没有应用,在“项目设置”页面中添加应用

在“添加应用”页面中设置基础信息

开通需要使用的serverless服务

2.进入开发者工具 创建端云项目

开发者工具登录华为账号

选择云开发基础模板

关联应用

项目结构

端云一体化开发工程目录分为三个子工程:端开发工程(Application)、云开发工程(CloudProgram)、端侧公共库(External Libraries)

云开发工程(CloudProgram)

3.部署云开发工程

在云开发工程目录上右键,点击Deploy Cloud Program

部署完成即可体验云开发基础模板

2、云函数

云函数开发

> 云函数承担传统应用后端接口的职责,在云函数内部编写业务逻辑,执行数据库访问、第三方Api调用等操作,开发者可以在云侧工程下开发云函数资源,包括创建函数、调试函数、部署函数。

1.创建函数

右击“cloudfunctions”目录,选择“New > Cloud Function”

输入函数名称后,点击“OK”,函数名称仅支持小写英文字母、数字、中划线(-),首字符必须为小写字母,结尾不能为中划线(-)。

2.调试函数

函数开发过程中,可在本地进行调试,也可以将函数部署到AGC云端后,在本地触发调用云端函数。

右击“cloudfunctions”目录,选择“Run Cloud Functions”。

查看“Run”面板。如果出现“Cloud Functions loaded successfully”,表示所有函数已成功加载到本地运行的HTTP Server中,并生成对应的POST URL。

在菜单栏选择“Tools > CloudDev > Cloud Functions Requestor”,使用Cloud Functions Requestor触发函数调用。

在弹出的“Cloud Functions Requestor”面板,填写触发事件参数。

3.部署函数

完成函数代码开发后,您可将函数部署到AGC控制台,支持单个部署和批量部署。

单个部署

右击需部署的函数目录,选择“Deploy Function”。

“底部状态栏右侧将展示函数打包与部署进度。

耐心等待,直至出现“Deploy successfully”消息,表示函数已成功部署。

登录[AppGallery Connect](https://developer.huawei.com/consumer/cn/service/josp/agc/index.html),进入当前项目的云函数服务菜单,可查看到您刚刚部署的函数,函数名称与本地工程的函数目录名相同。

批量部署指将整个云函数目录下创建的所有函数同时部署到AGC控制台。

右击“cloudfunctions”目录,选择“Deploy Cloud Functions”。

4.函数开发

入口方法

入口方法定义如下:

```

module.exports.myHandler = function(event, context, callback, logger){}

```

- myHandler:入口方法名称。

- event:调用方传递的事件对象,JSON格式。具体内容请参见[event对象]

(https://developer.huawei.com/consumer/cn/doc/development/AppGallery-connect-Guides/agc-cloudfunction-appx-event-0000001620581529#section12463185072710)。

- context:函数运行时上下文对象,封装了日志接口、回调接口、环境变量env对象等。

- callback:事件处理结果。

- logger:记录日志。

函数必须通过显示调用callback(object)将事件处理结果返回给AGC,结果可以是任意对象,但必须与JSON.stringify兼容,AGC会将结果转换成JSON字符串后,返回给调用方。callback执行完成,函数即执行结束。

函数调用

1. **在“项目设置”页面下载配置文件“agconnect-services.json”**

2. **将“agconnect-services.json”文件拷贝到DevEco Studio项目的任意应用级目录下,本文直接放在“entry/src/main/ets”目录下。**

3. **添加配置文件后,需要在DevEco Studio项目中配置SDK依赖**

   - 打开DevEco Studio entry目录下的“oh-package.json5”文件,添加依赖

     ```js   

 "dependencies": {

       "@hw-agconnect/hmcore": "^1.0.1",

       "@hw-agconnect/cloud": "^1.0.1"

     }

     ```

   - 右上方出现“Sync Now”链接,点击“Sync Now”等待同步完成。

2. **集成AGC SDK**

   - 在您的项目中导入agc组件,导入agconnect-services.json文件。

     ```js     

// agconnect-services.json可放置在任意路径,本例中,agconnect-services.json放置在EntryAbility.ts的上级目录。

     // @ts-ignore

     import json from '../agconnect-services.json';  // DevEco import 非Ets/TS文件时会报错,可以加上@ts-ignore,不影响编译。

     import { initialize } from '@hw-agconnect/hmcore';

     ```

   - 在您的应用初始化阶段使用context初始化SDK,推荐在EntryAbility的onCreate中进行。

     ```js   

 //初始化SDK

     onCreate(want, launchParam) {

       initialize(this.context, json);

     }

     ```

   - 在“entry/src/main/module.json5”文件中添加网络权限。

   -

     ```js   

 "requestPermissions": [

       {

         "name": "ohos.permission.INTERNET"

       }

     ]

     ```

   - **集成SDK可能会碰到的so文件优先级问题**

     在entry/build-profile.json5文件中添加配置

     ```js   

 {

       "buildOption": {

         "napiLibFilterOption": {

           "pickFirsts": [

             "**/1.so"

           ],

           "pickLasts": [

             "**/2.so"

           ],

           "excludes": [

             "**/3.so"

           ],

           "enableOverride": true

         },

       }

     }

     ```

3. **应用集成了云函数SDK后,可以在应用内直接通过SDK API调用AGC中的云函数,云函数SDK与AGC的函数调用基于HTTPS的安全访问。**

   ````js 

 //引入模块

   import cloud from "@hw-agconnect/cloud";

   

   let callFun = async ()=>{

       let functionResult = await cloud.callFunction({

          name:"函数名",

          params:{//参数 函数内部通过event.body获取

           "param1":"val1",

           "param2":"val2"

          }

       });

       console.log(functionResult.getValue())//拿到函数响应的结果

   }

   ````

3、云数据库

云数据库开发

> 云数据库是一款支持端云数据协同管理、可扩展的Serverless数据库产品,提供简单易用的多平台原生SDK,应用可以通过SDK直接访问云侧数据库

1.新增和导出对象类型文件

创建新的对象类型

输入“对象类型名”为“BookInfo”后,点击“下一步”

新增如下表字段后,点击“下一步”

| 字段名称 | 类型    | 主键 | 非空 | 加密 | 默认值 |

| -------- | ------- | ---- | ---- | ---- | ------ |

| id       | Integer | ✓    | ✓    | –    | –      |

| bookName | String  | –    | –    | –    | –      |

| author   | String  | –    | –    | –    | –      |

按照如下要求设置各角色权限后,点击“下一步”

| 角色       | query | upsert | delete |

| ---------- | ----- | ------ | ------ |

| 所有人     | ✓     | ✓      | ✓      |

| 认证用户   | ✓     | ✓      | ✓      |

| 数据创建者 | ✓     | ✓      | ✓      |

| 管理员     | ✓     | ✓      | ✓      |

点击“确定”。创建完成后返回对象类型列表,可以查看已创建的对象类型。

勾选创建的BookInfo对象类型,点击“导出”。若不勾选对象类型,默认导出所有对象类型

导出“json格式”和“js格式”文件,导出的文件在后续步骤用于添加至本地开发环境

新增存储区

2.在项目中使用

集成SDK,和云函数的用到的SDK一致

**加载对象类型文件**

将下载的两个文件放入ets/db/book/目录下

引入并使用

```js

// 注意目录,目录可以自定义

import { BookInfo } from './BookInfo';

import schema from './Bookinfo.json';

//QuickStartDemo存储区名称

async function upsert () {

    const record = await cloud.database({objectTypeInfo: schema, zoneName: "QuickStartDemo"})

    .collection(BookInfo)

    .upsert({

        "id":2000,

        "bookName" : "book_name",

        "author" : "huawei"

     });

}

```

查询数据

```js

const resultArray = await cloud.database({objectTypeInfo: schema, zoneName: "QuickStartDemo"})

.collection(BookInfo)

.query()

.get();

```

[更多数据库操作]

(https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-Guides/agc-clouddb-otheroperations-harmonyosts-0000001626432634)

4、认证服务

认证服务

> 认证服务可以为应用快速构建安全可靠的用户认证系统,开发者只需在应用中访问认证服务的相关能力,而不需要关心云侧的设施和实现。

开发步骤

1.申请手机注册的验证码

```js

import cloud from '@hw-agconnect/cloud';

import { Auth, VerifyCodeAction } from '@hw-agconnect/cloud';



cloud.auth().requestVerifyCode({

    action: VerifyCodeAction.REGISTER_LOGIN,

    lang: 'zh_CN',

    sendInterval: 60,

    verifyCodeType: {

        phoneNumber: '138********',

        countryCode: '86',

        kind: "phone"

    }

}).then(verifyCodeResult => {

    //验证码申请成功

}).catch(error => {

    //验证码申请失败

});

```

2.使用手机号码注册用户

调用[Auth.createUser](https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-References/harmonyos-arkts-auth-0000001680370685#section19861514132515)注册用户。注册成功后,系统会自动登录,无需再次调用登录接口。

```js

cloud.auth().createUser({

    kind: 'phone',

    countryCode: '86',

    phoneNumber: '138********',

    password: 'your password',//可以给用户设置初始密码,后续可以用密码来登录

    verifyCode: 'xxxx'

}).then(result => {

    // 创建用户成功

}).catch(error => {

    // 创建用户失败

})

```

3.登录

```js

cloud.auth().signIn({

    credentialInfo: {

        kind: 'phone',

        phoneNumber: '138********',

        countryCode: '86',

        password: 'your password'

    }

}).then(user => {

    //登录成功

}).catch(error => {

    //登录失败

});

```

4.在应用的登录界面

初始化[Auth](https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-References/harmonyos-arkts-auth-0000001680370685)实例,获取AGC的用户信息,检查是否有已经登录的用户。

如果有,则可以直接进入用户界面,否则显示登录界面。

```js

cloud.auth().getCurrentUser().then(user=>{

    if(user){

        //业务逻辑

       

    }

});

```

| 类型   | 方法名及描述                                                 |

| :----- | :----------------------------------------------------------- |

| string | [getUid](https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-References/harmonyos-arkts-authuser-0000001680210801#section1312317535214)()获取用户ID,此ID由AGConnect生成。 |

| string | [getEmail](https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-References/harmonyos-arkts-authuser-0000001680210801#section1320432912212)()获取用户邮箱。 |

| string | [getPhone](https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-References/harmonyos-arkts-authuser-0000001680210801#section1169817018235)()获取用户手机号码。 |

| string | [getDisplayName](https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-References/harmonyos-arkts-authuser-0000001680210801#section948316131197)()获取用户名称。 |

| string | [getPhotoUrl](https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-References/harmonyos-arkts-authuser-0000001680210801#section1063155522017)()获取用户头像。 |

| string | [getProviderId](https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-References/harmonyos-arkts-authuser-0000001680210801#section1324190192617)()获取当前用户的提供者,第三方认证平台的名称。 |

5.设置用户头像及昵称

```js

cloud.auth().getCurrentUser().then(user => {

  user.updateProfile({

    photoUrl: "https://xxx.png",

    displayName: "HamonyOSUser"

  })

})

```

6.退出登录

```js

cloud.auth().signOut().then(() => {

    //登出成功

}).catch(error => {

    //登出失败

});

```

| 错误码                                | 错误码值  | 说明                                                         |

| ------------------------------------- | --------- | ------------------------------------------------------------ |

| NULL_TOKEN                            | 1210001   | Token为空,建议重新登录。                                 |

| NOT_SIGN_IN                           | 1210002   | 当前无已登录用户。                                           |

| USER_LINK_FAILED                      | 1210003   | 用户关联失败。                                               |

| USER_UNLINK_FAILED                    | 1210004   | 用户取消关联失败。                                       |

| ALREADY_SIGN_IN_USER                  | 1210005   | 已经使用一个帐号登录,在未登出情况下使用此帐号或者其他帐号登录。 |

| FAIL_TO_GET_ACCESS_TOKEN              | 1210006   | 获取Access Token失败。                                       |

| FAIL_TO_UPDATE_PROFILE                | 1210007   | 更新用户信息失败。                                           |

| FAIL_TO_UPDATE_EMAIL                  | 1210008   | 更新用户邮箱失败。                                           |

| CREDENTIAL_INVALID                    | 1210009   | 凭证信息不合法。                                             |

| INLVLID_EMAIL                         | 203817223 | 输入的邮箱地址不合法。                                       

| INLVLID_PHONE                         | 203817224 | 输入的手机号码不合法。                                    |

| GET_UID_ERROR                         | 203817728 | 获取用户ID失败。                                   |

| UID_PRODUCTID_NOT_MATCH               | 203817729 | 用户ID和项目ID不匹配。                                       |

| GET_USER_INFO_ERROR                   | 203817730 | 获取用户信息失败。                                           |

| AUTH_METHOD_NOT_SUPPORT               | 203817732 | 当前认证微服务部署了4个局点,每个局点支持的认证方式不同。    |

| PRODUCT_STATUS_ERROR                  | 203817744 | 项目没有开通认证服务。                                       |

| PASSWORD_VERIFICATION_CODE_OVER_LIMIT | 203817811 | 密码验证码次数超过限制。                                     |

| INVALID_TOKEN                         | 203817984 | Client Token不可用。                                         |

| INVALID_ACCESS_TOKEN                  | 203817985 | Access Token不可用。                                         |

| INVALID_REFRESH_TOKEN                 | 203817986 | Refresh Token不可用。用户的Refresh Token过期,重新登录,获取新的Refresh Token。 |

| TOKEN_AND_PRODUCTID_NOT_MATCH         | 203817987 | Token和Product Id不匹配,建议检查“agconnect-services.json”是否与平台上申请的信息一致。 |

| AUTH_METHOD_IS_DISABLED               | 203817988 | 不支持的认证方式。                                           |

| ACCESS_TOKEN_OVER_LIMIT               | 203817991 | AccessToken数量超过了限定数量,配额是每个项目每个用户每小时500个。 |

| FAIL_TO_USER_LINK                     | 203817992 | 关联用户失败。                                               |

| FAIL_TO_USER_UNLINK                   | 203817993 | 取消用户关联失败。                                           |

| ANONYMOUS_SIGNIN_OVER_LIMIT           | 203818019 | 同一IP下的匿名用户登录超过限制,配额是每小时100个请求。      |

| INVALID_APPID                         | 203818020 | AppID不可用。                                                |

| INVALID_APPSECRET                     | 203818021 | App Secret不可用。                                           |

| PASSWORD_VERIFY_CODE_ERROR            | 203818032 | 密码和验证码错误。                                           |

| SIGNIN_USER_STATUS_ERROR              | 203818036 | 用户被开发者停用。                                           |

| SIGNIN_USER_PASSWORD_ERROR            | 203818037 | 用户密码错误。                                               |

| PROVIDER_USER_HAVE_BEEN_LINKED        | 203818038 | 身份验证提供方已经被其他用户绑定。                           |

| PROVIDER_HAVE_LINKED_ONE_USER         | 203818039 | 帐号中该身份验证提供方类型已经被绑定过。                     |

| FAIL_GET_PROVIDER_USER                | 203818040 | 获取身份验证提供方用户失败。                                 |

| CANNOT_UNLINK_ONE_PROVIDER_USER       | 203818041 | 不能对单一的身份验证提供方做取消关联操作。                   |

| VERIFY_CODE_INTERVAL_LIMIT            | 203818048 | 在发送间隔内发送验证码。                                     |

| VERIFY_CODE_EMPTY                     | 203818049 | 验证码为空。                                                 |

| VERIFY_CODE_LANGUAGE_EMPTY            | 203818050 | 验证码发送语言为空。                                         |

| VERIFY_CODE_RECEIVER_EMPTY            | 203818051 | 验证码接收器为空。                                           |

| VERIFY_CODE_ACTION_ERROR              | 203818052 | 验证码类型为空。                                             |

| VERIFY_CODE_TIME_LIMIT                | 203818053 | 验证码发送次数超过限制。                                     |

| ACCOUNT_PASSWORD_SAME                 | 203818064 | 用户名密码一致。                                             |

| PASSWORD_STRENGTH_LOW                 | 203818065 | 密码强度太低。                                               |

| UPDATE_PASSWORD_ERROR                 | 203818066 | 更新密码失败。                                               |

| PASSWORD_SAME_AS_BEFORE               | 203818067 | 密码与老密码相同。                                           |

| PASSWORD_IS_EMPTY                     | 203818068 | 密码为空。                                                   |

| PASSWORD_TOO_LONG                     | 203818071 | 密码太长。                                                   |

| SENSITIVE_OPERATION_TIMEOUT           | 203818081 | 敏感操作的最近登录时间超时。                                 |

| ACCOUNT_HAVE_BEEN_REGISTERED          | 203818082 | 帐号已经被注册。                                             |

| UPDATE_ACCOUNT_ERROR                  | 203818084 | 更新帐号失败。                                               |

| USER_NOT_REGISTERED                   | 203818087 | 用户没有注册。                                               |

| VERIFY_CODE_ERROR                     | 203818129 | 验证码错误。                                                 |

| USER_HAVE_BEEN_REGISTERED             | 203818130 | 用户已经被注册。                                             |

| REGISTER_ACCOUNT_IS_EMPTY             | 203818132 | 注册帐号为空。                                               |

| VERIFY_CODE_FORMAT_ERROR              | 203818134 | 验证码格式错误。                                             |

| VERIFY_CODE_AND_PASSWORD_BOTH_NULL    | 203818135 | 验证码和密码都为空。                                         |

| SEND_EMAIL_FAIL                       | 203818240 | 发送邮件失败。                                               |

| SEND_MESSAGE_FAIL                     | 203818241 | 发送短信失败。                                               |

| CONFIG_LOCK_TIME_ERROR                | 203818261 | 密码/验证码最大尝试次数超过设定值后对帐号进行冻结处理,冻结期间用户无法使用该帐号进行密码验证/验证码验证。 |

  • 26
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值