Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Cloud development Cloud development capabilities


May 22, 2021 Mini Program Cloud Development Study Guide


Table of contents


In the previous section, we roughly experienced cloud development: cloud development services were launched, equivalent to having a Nodejs environment in the cloud, where we could deploy cloud functions to the cloud. By invoking cloud functions, uploading pictures, operating databases, and using some open interfaces for small programs through cloud development capabilities, here's a better understanding of cloud development capabilities, as well as enhanced understanding of cloud testing, on-premises debugging, and on-premises Console log printing, and cloud log printing.

Programming to write a project is like doing a series of sophisticated and complex experiments, you can not always bother others to help you solve the problem, but to master debugging, testing, log printing and other means to check that every step of the operation is correct, you need to learn to view the wrong information, if the incorrect problem is where, what problems, you can be targeted to search, targeted to consult others.

On-premises debugging and cloud testing

In order to give us a clearer understanding of the process of operating a cloud function in its entirety and the importance of on-premises debugging and cloud testing, we take the rectangular edge length (a, b) as an example of a simple mathematical formula for devers and areas.

Step 1: Create a new cloud function

First we right-click on the root of the cloud function (i.e. the cloudfunctions folder), select the new Nodejs cloud function, the function named rectangular English rectangle, and then open index.js, modify the contents of the return as follows:

  1. exports.main = async (event, context) => {
  2. const wxContext = cloud.getWXContext()
  3. return {
  4. circum:(event.width+event.height)*2,
  5. area:event.width*event.height
  6. }
  7. }

circumverse is the circumnthese, the circumnthese is (width width plus height height✖️ 2; the area is the area, the area is the width width✖️ height height, as long as we later pass in the rectangular parameter width width and height height (after which we will tell you how to pass), you can get the perith and area of the rectangle.

After building the cloud function, we right-click on the cloud function directory, that is, the rectangle folder, choose to open in the terminal, using npm install to install the dependency.

  1. npm install

Step 2: Is the on-premises debug cloud function correct?

For a complex cloud function, it's a good idea to test the cloud function locally before deploying and uploading it to the cloud. S o how do you test it locally? Right-click on the cloud function directory, also known as the rectangle folder, select the local debugging (this way into the local debugging will turn on the local debugging of the rectangle by default), modify the following code:

  1. {
  2. "key": "value"
  3. }

We assign the parameter width width and height height (note that the JSON format is passed, the last argument cannot end with a comma, for example, the assignment is 3 and 6:

  1. {
  2. "width": 3,
  3. "height":7
  4. }

Then click on the call, if the display function executes successfully (note is still in debugging the console tag), and get the deverage circum and area area results of 20, 21, respectively, which proves that the cloud function is not wrong, then we can deploy and upload to the cloud.

Step 3: The cloud tests whether the cloud function is correct

Open the cloud function tab of the cloud development console, find the rectangle cloud function, click on the cloud test, and we assign the parameters and modify the following code:

  1. {
  2. "key1": "test value 1",
  3. "key2": "test value 2"
  4. }

For example, give the width width a value of 4 and a height height of 7, i.e. the code is modified to:

  1. {
  2. "width": 4,
  3. "height": 7
  4. }

Then click Run Test (wait a while) to see the results of the test, and if the results are returned as follows, the cloud function in the cloud can be called normally:

  1. {"circum":22,"area":28}

The results of the calls to the cloud test can also be found in the logs of the cloud development console cloud functions.

In the first section we want to trigger a cloud function, we need to write a component (such as button) in the small program page and bind the event handler, and then use wx.cloud.callFunction () in the event handler (or in the life cycle function of the page) to call the cloud function, in this way to trigger the cloud function, it will be cumbersome, while local debugging and cloud testing can directly trigger the cloud function to view the results, greatly improving the convenience of debugging.

The call to a cloud function uses an event-triggering model, and calls to small programs, local debugging, and cloud testing all trigger call events for cloud functions, where local debugging calls are not cloud functions in the cloud, but cloud functions on-premises in small programs.

Small tasks: Rectangle cloud functions need to pass in two parameters to return values, some cloud functions, such as the previous login cloud function do not need incoming parameters, do you know how to do on-premises debugging and cloud testing? In the local debugging request method has manual trigger and simulator trigger, turn on the simulator trigger, click on the first section "click to get openid" button to try (note that at this time called the local cloud function, modify the login cloud function do not upload to try);

Small terminals and service side

Initialization of the small terminal and the cloud

By default, small programs can create two environments, both of which have cloud function configurations, databases, cloud storage, and independent isolation, and there will be two environment switching scenarios in development (one for production and one for test environments), which are distinguished by their environment IDs, which should be noted when initializing small programs and the cloud.

As we described earlier, the initialization of a small program is .js using wx.cloud.init in the app file, as follows:

  1. wx.cloud.init({
  2. env: 'my-env-id', //可以填写生产环境或者测试环境的环境ID
  3. traceUser: true,
  4. })

Env here only determines the cloud environment for small terminal API calls (e.g. cloud functions, cloud storage, databases, after all, both environments), and not the environment in which APIs are called in cloud functions. In the developer tool's console, the default environment is also printed: the default environment for the initialization of the current code is your default environment ID

The default environment for initializing the current code is your default environment ID

The environment called by the API in the cloud function can also be set using initialization.

  1. cloud.init({
  2. env: cloud.DYNAMIC_CURRENT_ENV,
  3. })

cloud. D YNAMIC_CURRENT_ENV settings API default environment is equal to the current environment. I t is recommended that all cloud functions be initialized using the above method, that is, the value of env is configured as cloud. DYNAMIC_CURRENT_ENV or use your environment ID, don't be empty.

About wx-server-sdk

Every cloud function uses the wx-server-sdk Node package, and to use this package you need a Nodejs environment, where the small terminal needs to download Nodejs ourselves (previously downloaded), and the cloud brings its own Nodejs environment. S o what exactly is this wx-server-sdk? We can open its npm package address:

npm package address: wx-server-sdk package address

In the Dependencies tab you can see that wx-server-sdk relies on tcb-admin-node, protobufjs, tslib three packages, where tcb-admin-node is the core, learning children's shoes can look at its technical documentation.

Technical documentation: Github address for tcb-admin-node

async and await

The success, fail, and complete callbacks are no longer compatible in wx-server-sdk and only return Promise. I n cloud functions, there are also often asynchronous operations that need to be handled, and after the asynchronous operation is complete, the results are returned to the caller, which we can do by returning a Promise method in the cloud function. P romise represents the result returned by the asynchronous operation. In the newly created cloud function, you will see a statement like this (with async):

  1. exports.main = async (event, context) => {
  2. }

Async indicates that there are asynchronous operations in the function, and the return value of the async function is a Promise object. You'll also encounter await later, indicating that the expression that follows it needs to wait for the result; and the copy object's thorn() method (somewhat similar to the success callback function) and the catch() method (a bit like the fail callback function), which we'll often encounter later, can't understand and don't matter, and we'll recommend the cloud function to use the above writing when you write.

Considerations for cloud functions

  1. 在云函数部署并上传到云端之后,更新里面的文件比如index.jsconfig.json,建议右键点击更新好的文件(不是云函数目录)选择云函数增量上传:更新文件,不建议通过上传并部署所有文件的方式,否则在几分钟内会出现云函数调用失败的情况;
  2. 删除一个云函数之后,不建议再新建一个同名的云函数并上传部署,否则在十多分钟内会出现云函数调用失败的情况,建议换一个云函数名,比如login换成user,在小程序端使用 wx.cloud.callFunction({name: ''})调用云函数时把name的值换成user就可以了
  3. 调用云函数时,我们还可以在开发者工具调试面板的NetWork标签查看调用云函数的情况。

Get user information and sign in

In the Lifecycle section, we'll take a look at how to use the wx.getUserInfo API and get user information (such as avatars, nicknames) through the component's open-type "getUserInfo", and let's go into more detail about the combination of rights-free logins for cloud development and user information.

The use of open-type "getUserInfo" to obtain user information works the same as the basic effect of the wx.getUserInfo API, the difference being that the wx.getUserInfo approach is best called after the user allows access to public information (i.e. the value of the userInfo is true). I f the user rejects the authorization there will be no more pop-up windows (unless the user deletes your little program for re-use), the call will fail, and the user will use the component by actively clicking, and even if the user refuses, the user will still pop up the authorization pop-up window. Therefore, it is recommended to use components to obtain user authorization before using wx.getUserInfo to obtain user information.

Get user information through button

Using the developer tool to create a new login page, and then entering the following code in login.wxml, we get the user's information in a component way:

  1. <button open-type="getUserInfo" bindgetuserinfo="getUserInfomation">点击获取用户信息</button>
  2. <image src="{{avatarUrl}}"></image>
  3. <view>{{city}}</view>
  4. <view>{{nickName}}</view>

Initialize avatarUrl, nickName, and city in the data of the logo .js, and when the user information is not obtained, replace it with a default picture, the nickname shows that the user is not logged in, and the city appears unknown:

  1. data: {
  2. avatarUrl: '/images/user-unlogin.png',
  3. nickName:"用户未登陆",
  4. city:"未知",
  5. },

Then enter .js code in the login file, in the event handler getUserInfomation we can print the object, open-type, "getUserInfo" component of the object's object in the detail:

  1. getUserInfomation: function (event) {
  2. console.log('getUserInfomation打印的事件对象', event)
  3. let { avatarUrl, city, nickName}= event.detail.userInfo
  4. this.setData({
  5. avatarUrl,city, nickName
  6. })
  7. },

The acquired avatarUrl, city, nickName is assigned to data via theis.setData(). After compilation, click on the get user information button, the first will pop up the authorization window, when the user confirms, the user's information will be displayed.

Get the user's HD avatar

We found that the obtained avatar is not very clear, because the default avatar size is 132 132 (UserInfo user avatar description), if you change the 132 behind the avatarUrl link to 0, you can get 640 640 size avatar:

  1. getUserInfomation: function (event) {
  2. let { avatarUrl, city, nickName}= event.detail.userInfo
  3. avatarUrl = avatarUrl.split("/")
  4. avatarUrl[avatarUrl.length - 1] = 0;
  5. avatarUrl = avatarUrl.join('/');
  6. this.setData({
  7. avatarUrl,city, nickName
  8. })
  9. },

User information is displayed when the page loads

In the case of user authorization and user information, refresh the page or make a page jump, the user's personal information will not be displayed, because the getUserInfomation event handler clicks on the component triggered, we need to be able to trigger when the page loads to get user information.

We can enter the .js in the onLoad lifecycle function of the login and call the wx.getUserInfo() API when the user authorizes it:

  1. wx.getSetting({
  2. success: res => {
  3. if (res.authSetting['scope.userInfo']) {
  4. wx.getUserInfo({
  5. success: res => {
  6. let { avatarUrl, city, nickName } =res.userInfo
  7. this.setData({
  8. avatarUrl, city, nickName
  9. })
  10. }
  11. })
  12. }
  13. }
  14. });

This way, when we load the page, the user's information can be displayed, but the avatar here is taken back from the API, and it is not clear. Of course we can replace the link to the avatar as before, but if every page is written like this, there are two ways to solve it, one is to store the HD avatar in the cache, and the other is to encapsulate the code as a component (you can study how to customize the component yourself).

openid, user information, and login

Although we have obtained the user's avatar, nickname and other information, but this can not be called the real meaning of the login, only to get the user's identity of the only ID is openid, we can be user behavior such as likes, comments, published articles, favorites and so on linked to the user, the user these behaviors are related to the database, but can determine the likes, comments, articles, collection of these data and user relations is openid, T his means that as long as the openid is obtained, it means that the user is logged in, and getting user information (such as avatars, nicknames) is just an add-on service, both of which can be completely independent. W ithout openid, we can't store user information in a database, and we can't let users customize user information. Openid is an important bridge, whether it's user behavior or user information.

With the previous login cloud function, we can already get the user's openid. G etting a naturally trusted user login without maintaining complex forensic mechanisms is an important advantage of cloud development. Openid plays an important role in both cloud storage and cloud databases.

Upload images to cloud storage on the small terminal

To upload an image to cloud storage, you will use it to wx.cloud.uploadFile, which is the API of the small terminal, which uploads the files from the local resource, which is the temporary file, to the cloud storage. In the previous "Pictures, Caches, and Files" section, we learned how to upload images to a temporary file of a small program, and to upload a temporary file to cloud storage, you need to call the wx.cloud.uploadFile API.

Technical documentation: wx.cloud.uploadFile

In the wx.cloud.uploadFile technical documentation, you can see that to call the API, you need to get the picture of filePath, in the small program for the path of the temporary file, that is, to upload to the small program of the temporary file path assigned to it;

Using the developer tool to add the following code to login.wxml, the code is basically the same as in the previous sections, and you can review the previous content:

  1. <button bindtap="chooseImg">选择图片</button>
  2. <image mode="widthFix" src="{{imgurl}}"></image>

Then initialize .js in the data of the login, where the imgurl is a string,

  1. data: {
  2. imgurl: "",
  3. },

Then add the .js Img in the login file, and let's review the knowledge of the temporary file:

  1. chooseImg: function () {
  2. wx.chooseImage({
  3. count: 1,
  4. sizeType: ['compressed'],
  5. sourceType: ['album', 'camera'],
  6. success: function (res) {
  7. console.log(res)
  8. console.log(res.tempFilePaths)
  9. }
  10. })
  11. },

After compiling, upload an image, in the console we can see that res.tempFilePaths is an array format, and wx.cloud.uploadFile's filePath is a string, so we can assign the path (string) of the first picture to filePath when we upload:

  1. const filePath = res.tempFilePaths[0]

The processing of the file name and suffix

We know that a file consists of a file name and file suffix, such as tcb.jpg and cloudbase.png, jpeg description picture format is JPG format, and png description picture is PNG format, file name is the same and the same format is overwritten, if we change the file suffix at will, most files will not open. So the path to cloudPath cloud storage requires us to handle the file name and suffix.

When we upload the image to the temporary file of the small program, we can see what the temporary path looks like:

  1. http://tmp/wx7124afdb64d578f5.o6zAJs291xB-a5G1FlXwylqTqNQ4.esN9ygu5Hmyfccd41d052e20322e6f3469de87f662a0.png

The file name of the temporary path is not the original file name and becomes a long character, but the file format is the original file format (suffix). So cloudPath to enter the path of the file, you need to fill in the file name and file format, how to deal with this?

In the QuickStart gadget in the last section, files are uploaded to cloud storage in the following ways:

  1. const cloudPath = 'my-image' + filePath.match(/\.[^.]+?$/)[0]

That is, it names all uploaded images my-image, and the file suffix is the original file suffix (i.e. the file format remains unchanged). H ere's filePath.match (/. ^ .] ? ??$/) is the regular handling of the string, which we'll learn more about later. Let's start by entering the following code in the developer tool's console to see what it does:

  1. const filepath="http://tmp/wx7124afdb64d578f5.o6zAJs291xB-a5G1FlXwylqTqNQ4.esN9ygu5Hmyfccd41d052e20322e6f3469de87f662a0.png"
  2. filepath.match(/\.[^.]+?$/)[0]

Print to get the suffix of the temporary file, which is .png. This practice of naming all files my-image will result in the file being overwritten when the suffix is the same, and if we don't want the file to be overwritten, we need to give the file a different name, which we can do this:

  1. const cloudPath = `${Date.now()}-${Math.floor(Math.random(0, 1) * 1000)}` + filePath.match(/\.[^.]+?$/)[0]

Add a timestamp and a random number to the file name, which is calculated in milliseconds, and the random number is a positive integer within 1000, unless you upload hundreds of thousands of photos in 1 second (1 second x 1000 milliseconds), the file name will not be repeated.

Combined with the above, we can treat the success callback function of wx.chooseImage() as follows:

  1. success: function (res) {
  2. const filePath = res.tempFilePaths[0]
  3. const cloudPath = `${Date.now()}-${Math.floor(Math.random(0, 1) * 1000)}` + filePath.match(/\.[^.]+?$/)[0]
  4. wx.cloud.uploadFile({
  5. cloudPath,
  6. filePath,
  7. success: res => {
  8. console.log('上传成功后获得的res:', res)
  9. },
  10. })
  11. }

After compilation, we upload an image again will print the successful upload of the res object, which contains the image in the cloud storage fileID, pay attention to its file name and file suffix, and we can find in the cloud development console storage you uploaded the picture, that is, we upload the picture to the cloud storage can not directly get the download address of the picture.

The secondary directory of cloud storage

In storage we all put all the pictures under the root, there is no secondary directory, so can we build a secondary directory? Of course, yes, we can add a file path in front of cloudPath, for example:

  1. const cloudPath = `cloudbase/${Date.now()}-${Math.floor(Math.random(0, 1) * 1000)}` + filePath.match(/\.[^.]+?$/)[0]

Render cloud storage pictures to components

As we learned in the Component Support section of the last section, we can render fileID directly in some components of a small program. The chooseImg event handler, which synthesies the above, ends up with the following code (note this.setData's this point, where the success callbacks are written as arrow functions for convenience):

  1. chooseImg: function () {
  2. wx.chooseImage({
  3. count: 1,
  4. sizeType: ['compressed'],
  5. sourceType: ['album', 'camera'],
  6. success: res=> {
  7. const filePath = res.tempFilePaths[0]
  8. const cloudPath = `cloudbase/${Date.now()}-${Math.floor(Math.random(0, 1) * 1000)}` + filePath.match(/\.[^.]+?$/)[0]
  9. wx.cloud.uploadFile({
  10. cloudPath,
  11. filePath,
  12. success: res => {
  13. console.log('上传成功后获得的res:', res)
  14. const imgurl=res.fileID
  15. this.setData({
  16. imgurl
  17. })
  18. },
  19. })
  20. }
  21. })
  22. },
  1. 在云开发控制台的存储里,我们可以看到每张图片的详细信息都有上传者 Open ID,无论你是使用开发者工具在模拟器的小程序里上传还是预览在手机的小程序里上传,只要你用的是同一个微信账号,这个上传者openid都是一致的,云存储会自动记录上传者的openid

Small tasks: Combined with the knowledge of wx.chooseMessageFile() in the Pictures, Caches, and Files section, video, audio, PDF, Excel, etc. from client sessions (WeChat chat windows) are also uploaded to cloud storage.

The cloud function uploads images to the cloud store

Cloud development not only uploads files to cloud storage on a small terminal, but also uploads images to cloud storage through cloud functions, which are the cloud (a bit of Nodejs knowledge is involved here).

Technical documentation: uploadFile

Note that the API for uploading images by the cloud function belongs to the service-side API, unlike the wx.cloud.uploadFile, which is a small terminal API.

Use the developer tool to right-click on the root of the cloud function, that is, the cloud function folder, select a new Node.js yun function, the name of the cloud function is named uploadimg, right-click on the uploadimg folder, select the hard disk to open, and then copy a picture such as demo.jpg to go in, the file structure is as follows:

  1. uploadimg云函数目录
  2. ├── index.js
  3. ├── package.json
  4. ├── demo.jpg

Then open the .js and enter the following code:

  1. const cloud = require('wx-server-sdk')
  2. const fs = require('fs')
  3. const path = require('path')
  4. cloud.init({
  5. env: cloud.DYNAMIC_CURRENT_ENV,
  6. })
  7. exports.main = async (event, context) => {
  8. const fileStream = fs.createReadStream(path.join(__dirname, 'demo.jpg'))
  9. return await cloud.uploadFile({
  10. cloudPath: 'tcbdemo.jpg',
  11. fileContent: fileStream,
  12. })
  13. }

Then right-click on the uploadimg folder, choose to open in the terminal, enter the npm install installation dependency, then click on the uploadimg folder, choose to upload and deploy all the files (when the picture is also uploaded to the cloud).

Since the cloud test can't get the user login status information, we can't upload the picture to the cloud storage in the cloud test, we need to call it in a small program, and use the developer tool to enter the following code in login.wxml, that is, a new button that binds the uploadimg event handler to trigger:

  1. <button bindtap="uploadimg">云函数上传图片</button>

Then enter .js the login function, call the uploadimg cloud function in the event handler uploadimg, and return the res object after the call:

  1. uploadimg() {
  2. wx.cloud.callFunction({
  3. name: 'uploadimg',
  4. success: res => {
  5. console.log(res)
  6. }
  7. })
  8. },

After compilation, click on the cloud function upload image button, you can call the uploadimg cloud function, so that the uploadFile API will be the service/cloud image uploaded to the cloud storage inside, you can open the cloud development console cloud storage to see if there is a tcbdemo.jpg this picture.

Note that images uploaded to cloud storage in this way are not uploaded to the open ID of the uploader, and you can see the details of this image in the cloud storage.

Call the database

The import of the database

Before we can call the database, we need to have a database case that is closer to the actual one, so we put together a database file with the knowledge daily data used in the previous section. The cloud development database supports importing existing data as a file (json is recommended here).

Database download: Know the daily article data

Right-click on the link to store data.json on your computer. To make it easier for you to read and edit the contents of the data.json file, it is recommended that you use the Visual Studio Code Editor.

Code editor: Visual Studio Code

Editor's Hanhua and plug-in: Maybe the interface you installed vs Code is in English, you can refer to vsCode settings Chinese display, VS Code Hanhua.

Using the VS Code editor to open data.json, we find that the content and writing of the data are familiar to us, and that the knowledge that each record object is separated by the use of carriage returns, rather than commas, requires attention.

Open the cloud development console, create a new collection zhihu_daily in the database, import the jason file, there will be conflict mode selection when importing, see the following introduction, recommended for everyone to use upsert:

  • Insert: Always insert a new record
  • Upsert: Update if a record exists, or insert a new record

After import, the discovery database automatically adds a unique identity to each data (record_id.

The database is called by the small terminal

The way the database is called on the small terminal is simple: we can write the following code into an event handler, then click on the component trigger event handler to call it, we can write it directly to the lifecycle function of the page, and we can write it into the lifecycle function of the app.js siever.

Using the developer tool, write the following code .js the login function, we

  • Use wx.cloud.database () to obtain a reference to the database (equivalent to connecting the database);
  • Then use db.collection() to get a reference to the collection;
  • Then use College.get to get the records in the collection.

  1. const db = wx.cloud.database()
  2. db.collection('zhihu_daily')
  3. .get()
  4. .then(res => {
  5. console.log(res.data)
  6. })
  7. .catch(err => {
  8. console.error(err)
  9. })

After compilation, you can see the 20 database records called in the console (up to 20 records by default if you don't specify a limit).

The cloud function calls the database

You can also call the database using the cloud function, use the developer tool to right-click on the root of the cloud function, which is the cloudfunctions folder, select a new Node.js yun function, named zhihu_daily, and then open index.js and enter the following code:

  1. const cloud = require('wx-server-sdk')
  2. cloud.init({
  3. env: cloud.DYNAMIC_CURRENT_ENV
  4. })
  5. const db = cloud.database()
  6. exports.main = async (event, context) => {
  7. return await db.collection('zhihu_daily')
  8. .get()
  9. }

Then right-click on index.js and select the cloud function incremental upload: update the file, we can neither use the local debugging of the cloud function (to debug locally using npm install to install wx-server-sdk dependency), or use the cloud test to understand the cloud function call database.

Openid and database

In the database tab of the cloud development console, open the counters collection in the last section, where we can see that in addition to the _id field, each record has a _openid field that flags the creator of each record (that is, the user of the program). But if we use data created on the management side (console and cloud functions), such as the zhihu_daily we imported earlier, there will be no _openid field because these records belong to records created by administrators (not users).

We can customize _id (that is, add a _id field to the data and fill in any value), but we can't customize _openid. _ openid is created by default by the system at the time the document is created by the user of the program and can be used to identify and locate the document. Like cloud storage, database records are closely linked to openid.