diff --git a/docs/uniCloud/cf-functions.md b/docs/uniCloud/cf-functions.md index aef2df2ec56d30c1b7ada6ca7f2f2f1cb50bbee4..d44c8db8f778fc69ad44480b28a1795b8fdb1976 100644 --- a/docs/uniCloud/cf-functions.md +++ b/docs/uniCloud/cf-functions.md @@ -1,1424 +1,1424 @@ -## 简介@intro - -云函数是è¿è¡Œåœ¨äº‘端的 `JavaScript` 代ç ,是基于 `Node.js` 的扩展。 - -在常规的 `Node API` 基础上,uniCloud的云函数环境内置了`uniCloud`对象,这个对象内置了网络ã€æ•°æ®åº“ç‰å„ç§API。开å‘者未å¦ä¹ 过 `Node.js` 也没有关系,åªéœ€è¦çœ‹uniCloud的文档,掌æ¡è¿™ä¸ª`uniCloud`对象的APIå³å¯ã€‚ - -æ¯ä¸ªäº‘函数是一个js包,在云函数被调用时,由 serverless 调度系统分é…硬件资æºå¯åŠ¨ä¸€ä¸ª node 环境æ¥è¿è¡Œè¿™ä¸ªäº‘函数。 - -在HBuilderXä¸å¯ä»¥æ–°å»ºäº‘函数(HBuilderX 3.4 åŒæ—¶å¯ä»¥æ–°å»ºäº‘对象)。 - - -æ¯ä¸ªäº‘函数是一个目录,其ä¸æ™®é€šäº‘函数有`index.js`å…¥å£æ–‡ä»¶ï¼Œäº‘对象的入å£æ–‡ä»¶åˆ™æ˜¯`index.obj.js`。 - -一个最简å•çš„云函数åªéœ€è¦è¿™ä¸ªå…¥å£js文件,在里é¢ç¼–写代ç å³å¯ã€‚当然也å¯ä»¥åœ¨è¿™ä¸ªjsä¸require该云函数目录下的其他jsã€json文件。 - -云函数的é…置文件和 npm规范 相åŒï¼Œåœ¨äº‘函数目录下å¯æ–°å»ºä¸€ä¸ª package.json æ¥å˜æ”¾é…置。uniCloud云函数扩展了 package.jsonï¼Œå¢žåŠ äº†ä¸€äº›ç‰¹æœ‰çš„é…置项。[详è§](/uniCloud/cf-functions?id=packagejson) - -云函数å¯åŠ¨åŽå®žä¾‹ä¼šä¿ç•™ä¸€æ®µæ—¶é—´ï¼ˆå¦‚15分钟),超过ä¿ç•™æœŸåŽè‹¥è¯¥äº‘函数一直没有被å†è°ƒç”¨ï¼Œé‚£è¿™ä¸ªå®žä¾‹ä¼šè¢«é‡Šæ”¾ã€‚所以云函数有冷å¯åŠ¨çš„概念。ä¸è¿‡ç”±äºŽjs实例的å¯åŠ¨è¦æ¯”phpå’Œjava更快,所以js更适åˆserverlessæ–¹å¼ã€‚ - -**注æ„事项** -- 云函数内使用commonjs规范,ä¸å¯ä½¿ç”¨importã€export,å‚考:[commonjs模å—](http://nodejs.cn/api/modules.html#modules_modules_commonjs_modules) -- ä¸åŒé¡¹ç›®ä½¿ç”¨åŒä¸€ä¸ªæœåŠ¡ç©ºé—´æ—¶ï¼Œä¸å¯ä½¿ç”¨åŒå云函数。åŒå云函数会相互覆盖。 -- 在HBuilderX创建云函数时,如果新云函数与æœåŠ¡å™¨ä¸Šå·²å˜åœ¨åŒå云函数,会用新函数覆盖。所以应先选择从æœåŠ¡ç©ºé—´ä¸‹è½½äº‘函数。 -- å•ä¸ªäº‘函数大å°é™åˆ¶ä¸º10M(包å«`node_modules`),过大的云函数影å“è¿è¡Œæ€§èƒ½ï¼Œä¹Ÿä¼šå¢žåŠ 计费的gbs。åŒæ—¶è…¾è®¯äº‘支æŒåœ¨äº‘端安装`node_modules`,æ¤æ—¶ä¸å 用云函数体积。 -- uniCloud的阿里云版,暂ä¸å¯ä½¿ç”¨ç›¸å¯¹è·¯å¾„读å–文件(比如`fs.readFileSync('./info.txt')`),å¯ä»¥ä½¿ç”¨ç»å¯¹è·¯å¾„`fs.readFileSync(path.resolve(__dirname,'./info.txt'))` - -## 云函数的分类 - -云函数有若干å概念,包括 普通云函数ã€äº‘对象ã€å…¬å…±æ¨¡å—ã€clientDBçš„action云函数ã€uniCloud扩展库。 - -- äº‘å‡½æ•°ï¼šé€šè¿‡ä¼ ç»Ÿjson接å£æ–¹å¼å’Œå®¢æˆ·ç«¯é€šä¿¡ï¼Œå®¢æˆ·ç«¯ä½¿ç”¨`uniCloud.callfunction("")`调用云函数 -- 云对象:是通过å‰ç«¯å¯¼å…¥å¯¹è±¡æ¥æ“作的,客户端使用`uniCloud.importObject("")`导入云对象。详è§[云对象](/uniCloud/cloud-obj) -- 公共模å—:用于ä¸åŒçš„云函数/云对象,抽å–和共享相åŒä»£ç ,详è§[公共模å—文档](/uniCloud/cf-functions?id=公共模å—) -- action云函数:为了弥补clientDB客户端直接æ“作数æ®åº“çš„å±€é™è€Œè®¾è®¡çš„,详è§[clientDB action文档](/uniCloud/clientdb?id=action) -- uniCloud扩展库:为了è£å‰ªå’ŒæŽ§åˆ¶äº‘函数体积而设计的,一些ä¸å¤ªå¸¸ç”¨çš„功能比如Redis,独立为å¯é€‰æ‰©å±•åº“,é¿å…增大æ¯ä¸ªäº‘函数的体积,详è§[uniCloud扩展库](/uniCloud/cf-functions?id=扩展库) - -HBuilderXä¸uniCloud项目的云函数å‡åœ¨é¡¹ç›®çš„`uniCloud/cloudfunctions`目录下,目录结构如下: - -<pre v-pre="" data-lang=""> - <code class="lang-" style="padding:0"> -|——— cloudfunctions 云函数目录 -| │───common 云函数公用模å—目录 <a target="_blank" href="https://uniapp.dcloud.net.cn/uniCloud/cf-common">详情</a> -| | └──hello-common äº‘å‡½æ•°å…¬ç”¨æ¨¡å— -| | │──index.js 公用模å—代ç -| | └──package.json 公用模å—package.json -| │───uni-clientDB-actions -| │ └──new_action.js clientDB action代ç <a target="_blank" href="https://uniapp.dcloud.net.cn/uniCloud/clientdb?id=action">详情</a> -| │───function-name 云函数目录 -| │ │──index.js 云函数代ç -| │ └──package.json 包å«äº‘函数的é…置信æ¯ï¼Œå¦‚url化ã€å®šæ—¶è®¾ç½®ã€å¯ç”¨å†…å˜ç‰å†…容 <a target="_blank" href="https://uniapp.dcloud.net.cn/uniCloud/cf-functions?id=packagejson">详情</a> -| └───object-name 云对象目录 -| │──index.obj.js 云对象代ç -| └──package.json 包å«äº‘对象的é…置信æ¯ï¼Œå¯ç”¨å†…å˜ç‰å†…容 <a target="_blank" href="https://uniapp.dcloud.net.cn/uniCloud/cf-functions?id=packagejson">详情</a> - </code> -</pre> - -## 客户端和云函数的通信@clientcallfunction - -uni-appå®¢æˆ·ç«¯å’Œä¼ ç»ŸæœåŠ¡å™¨é€šä¿¡æ—¶ï¼Œä½¿ç”¨`uni.request`çš„ajax请求方å¼ã€‚uniCloud下ä¸å†ä½¿ç”¨å®ƒï¼Œæœ‰æ›´å¥½çš„云端一体的通信方å¼ã€‚ - -uniCloud体系里,客户端和æœåŠ¡ç«¯çš„云函数通信,有4ç§æ–¹å¼ï¼š - -| |ä¼ ç»Ÿçš„restfulæ–¹å¼|callfunctionæ–¹å¼|云对象方å¼|clientDBæ–¹å¼| -|:-:|:-:|:-:|:-:|:-:| -|简述 |通过é…ç½®[云函数URL化](/uniCloud/http)ï¼ŒæŠŠäº‘å‡½æ•°è½¬ä¸ºä¼ ç»Ÿçš„http链接 |云函数默认并ä¸è‡ªå¸¦http链接|把callfunction的函数å¼è°ƒç”¨ï¼Œå‡çº§ä¸ºæ¨¡å—化的对象调用|客户端直接æ“作云数æ®åº“| -|å‰ç«¯è°ƒç”¨æ–¹å¼|ä¼ ç»Ÿajax|uni-app客户端通过`uniCloud.callFunction(functionname)`æ¥è°ƒç”¨äº‘函数|uni-app客户端通过`uniCloud.importObject(objectname)`导入一个云对象,直接使用这个对象的方法 |uni-app客户端通过`<uniCloud-db>`组件或`uniCloud.database()` APIæ¥è®¿é—®uniCloudæ•°æ®åº“。也支æŒæé…actionäº‘å‡½æ•°è¿½åŠ æœåŠ¡å™¨é€»è¾‘ | -|适用场景 |http链接需è¦è‡ªå·±æ³¨å†ŒåŸŸå。如果å‰ç«¯æ˜¯uni-app,则ä¸æŽ¨è使用URL化。如果是éžuni-app的系统需è¦è®¿é—®äº‘函数,åªèƒ½ä½¿ç”¨URL化 |相比云函数URL,callfunctionæ›´åŠ å®‰å…¨ã€æ›´serverless,ä¸æš´éœ²åŸŸåå’Œip,ä¸æ€•æ”»å‡»ï¼Œä¹Ÿæ— 需注册域å|uni-app 3.4起支æŒã€‚相比callfunctionæ–¹å¼ã€‚代ç æ›´åŠ ç²¾ç®€ã€é€»è¾‘æ›´åŠ æ¸…æ™°ã€å¼€å‘æ›´åŠ é«˜æ•ˆ |如果uni-appå‰ç«¯å‘èµ·çš„æœåŠ¡å™¨è¯·æ±‚目的主è¦æ˜¯æŸ¥è¯¢æˆ–æ“作数æ®åº“,则推è使用clientDBæ–¹å¼| - -云函数是uniCloud的基础,本质上 clientDB å’Œ 云对象 都是建立在云函数上针对特定场景的优化。 -- clientDB针对的场景是数æ®åº“æ“作,它优化了å¯ä»¥ä¸å†™æˆ–少写æœåŠ¡å™¨ä»£ç -- 云对象针对的场景是éžæ•°æ®åº“æ“作或ä¸å®œå‰ç«¯æš´éœ²çš„æ•°æ®åº“æ“作时,和uni-app客户端的通信方å¼ã€‚它优化了代ç 结构,更精简ã€ç®€å• - - -### clientDBæ–¹å¼ - -**直观体验代ç 示例** - -clientDB分APIæ–¹å¼å’Œç»„件方å¼ï¼Œæ¤å¤„使用APIæ–¹å¼æ¥æ¼”示 -```js -// 客户端js直接æ“作云数æ®åº“,查询list表的数æ®ã€‚æ— éœ€æœåŠ¡å™¨ä»£ç -const db = uniCloud.database() // 获å–云数æ®åº“的引用 -db.collection('list').get() - .then((res)=>{ - // res 为数æ®åº“查询结果 - }).catch((err)=>{ - console.log(err); - }) -``` - -由于篇幅较长,å¦ä¹ clientDB需å¦è§æ–‡æ¡£[clientDB](clientdb.md) - -- clientDB适用的情况: - -如果客户端使用uni-appå¼€å‘,且å‘uniCloudæœåŠ¡ç©ºé—´çš„请求主è¦æ˜¯ä¸ºäº†æ“作云数æ®åº“ï¼ˆæ— è®ºå¢žåˆ æ”¹æŸ¥ï¼‰ï¼Œé‚£ä¹ˆæŽ¨è使用clientDBæ–¹å¼ï¼Œç”±uni-app客户端直接æ“作云数æ®åº“。 - -如果æ“作数æ®åº“çš„åŒæ—¶ï¼Œè¿˜éœ€è¦åŒæ—¶æ‰§è¡Œä¸€äº›äº‘函数,å¯ä»¥ä½¿ç”¨clientDBçš„action云函数。 - -- clientDBä¸é€‚用的情况: - -1. 请求ä¸æ“作云数æ®åº“,比如å‘外部web系统å‘请求ã€æ“作redisã€åˆ 除云文件ç‰ï¼› -2. æ“作的云数æ®åº“请求ä¸å¸Œæœ›æš´éœ²åœ¨å‰ç«¯ï¼› -3. æ•°æ®åº“表和å—段数é‡å¤šè€ŒæŽ¥å£æ•°é‡å°‘。给æ¯ä¸ªæ•°æ®é…ç½®æƒé™çš„工作é‡è¶…过了控制少数接å£æƒé™çš„工作é‡ï¼› -4. æƒé™ä½“系较å¤æ‚,除了用户和管ç†å‘˜å¤–还有较多其他æƒé™æ¡ä»¶æˆ–动æ€æƒé™ã€‚æ¤æ—¶åœ¨schemaå’Œactionä¸ç¼–写代ç çš„å¤æ‚度超过了写接å£ã€‚ - -### äº‘å¯¹è±¡æ–¹å¼ - -云对象和clientDB最大的区别,是云对象把数æ®åº“æ“作(以åŠå…¶ä»–逻辑)å°è£…在云对象的方法里é¢ã€‚ - -å®ƒæ— æ³•åƒclientDBé‚£æ ·æ— éœ€å¼€å‘æœåŠ¡å™¨ä»£ç ,它ä»éœ€åœ¨å®¢æˆ·ç«¯å’Œäº‘端分别写代ç 。但它的应用场景ä¸å—é™åˆ¶ã€‚上文ä¸ä¸é€‚用clientDB的情况,都å¯ä»¥ä½¿ç”¨äº‘对象解决。 - -**直观体验代ç 示例** - -云端云对象代ç ,云对象å称:testco,有一个sum方法 - -```js -module.exports = { - sum(a, b) { - // æ¤å¤„çœç•¥aå’Œbçš„æœ‰æ•ˆæ€§æ ¡éªŒ - return a + b - } -} -``` - -然åŽåœ¨å®¢æˆ·ç«¯çš„jsä¸ï¼Œimport这个testco对象,调用它的sum方法 - -```js -const testco = uniCloud.importObject('testco') //第一æ¥å¯¼å…¥äº‘对象 -async function sum () { //注æ„方法或生命周期需使用async异æ¥æ–¹å¼ - try { - const res = await testco.sum(1,2) //导入云对象åŽå°±å¯ä»¥ç›´æŽ¥è°ƒç”¨è¯¥å¯¹è±¡çš„方法了,注æ„使用异æ¥await - console.log(res) // 结果是3 - } catch (e) { - console.log(e) - } -} -``` - -由于篇幅较长,å¦ä¹ 云对象需å¦è§æ–‡æ¡£[云对象](cloud-obj.md) - -clientDB和云对象å¯ä»¥æ··åˆä½¿ç”¨ï¼š -1. 比如官方æ供了[uni-id-pages](uni-id-pages.md),是基于云对象的登录注册系统,开å‘者å¯ä»¥å¯¼å‡ºè¿™ä¸ªæ’件处ç†è´¦æˆ·ä½“系,然åŽå‰©ä½™çš„业务如果ä¸ç®—å¤æ‚,就å¯ä»¥ä½¿ç”¨clientDBæžå®šã€‚ -2. 一个业务的用户端和admin端也å¯ä»¥æ˜¯ä¸åŒçš„æŠ€æœ¯æ ˆã€‚æ¯”å¦‚ä¸šåŠ¡ç«¯æœ‰å¤æ‚的动æ€æƒé™ï¼Œè€Œç®¡ç†ç«¯åªæœ‰ä¸€ä¸ªadmin管ç†å‘˜ä½¿ç”¨ï¼Œé‚£ä¹ˆadmin端使用[schema2code](schema2code.md)会éžå¸¸é«˜æ•ˆï¼Œè€Œè¿™äº›æŠ€æœ¯éƒ½åŸºäºŽclientDB。 - -### 普通云函数callFunctionæ–¹å¼ - -- 普通云函数适用的情况: - -在HBuilderX 3.5.2之å‰ï¼Œéœ€è¦URL化和定时è¿è¡Œæ—¶ï¼Œåªèƒ½ä½¿ç”¨æ™®é€šäº‘函数;在HBuilderX 3.5.2+,云对象也支æŒäº†URL化和定时è¿è¡Œã€‚ - -官方ä¸æŽ¨èå¼€å‘者使用云函数,有相关需求推è使用云对象替代云函数。 - -ç›®å‰å®˜æ–¹è¿˜æœªæ供基于云对象的router模å¼çš„框架,有相关需求å¯ä»¥ä½¿ç”¨ä¸‰æ–¹æ¡†æž¶ã€‚ - -**直观体验代ç 示例** - -```js -// 客户端å‘起调用云函数hellocfï¼Œå¹¶ä¼ å…¥dataæ•°æ® -uniCloud.callFunction({ - name: 'hellocf', - data: {a:1,b:2} -}).then((res) => { - console.log(res.result) // 结果是 {sum: 3} -}).catch((err) => { - console.error(err) -}) -``` - -```js -// 云函数hellocf的代ç ï¼ŒæŽ¥æ”¶åˆ°å®¢æˆ·ç«¯ä¼ é€’çš„data,并对其ä¸aå’Œbç›¸åŠ è¿”å›žç»™å®¢æˆ·ç«¯ -'use strict'; -exports.main = async (event, context) => { - //eventä¸ºå®¢æˆ·ç«¯ä¸Šä¼ çš„å‚æ•° - console.log('event : ', event) - //æ¤å¤„çœç•¥event.aå’Œevent.bçš„æœ‰æ•ˆæ€§æ ¡éªŒ - //返回数æ®ç»™å®¢æˆ·ç«¯ - return {sum : event.a + event.b} -}; - -``` - -由于篇幅较长,需å¦è§æ–‡æ¡£[云函数callfunctionæ–¹å¼](/uniCloud/cf-callfunction) - -### 云函数URLåŒ–æ–¹å¼ - -å¯ä»¥è®©äº‘函数/云对象生æˆä¸€ä¸ªHTTP URLã€‚è¿™æ ·éžuni-app应用,å¯ä»¥é€šè¿‡ajax请求和云函数/云对象通信。 - -在 uniCloud Web控制å°è¿›è¡ŒURL化é…置。 - -由于篇幅较长,需å¦è§æ–‡æ¡£[云函数URL化](http.md)。 - - -### uniCloudå“应体规范@resformat - -`uniCloudå“应体规范`(uniCloud response format),是DCloud制定的ã€æœåŠ¡å™¨ç»™å®¢æˆ·ç«¯è¿”回jsonæ•°æ®çš„一ç§å»ºè®®æ ¼å¼ã€‚ - -云对象ã€clientDBã€uni-id公共模å—å‡æ”¯æŒæ¤è§„范。 - -**ç”±æ¥** - -uniCloudæœåŠ¡å™¨ç»™å®¢æˆ·ç«¯è¿”回的数æ®æ ¼å¼ä¸€èˆ¬æ˜¯json,但jsonçš„æ ¼å¼å…·ä½“是什么没有约定。比如返回错误ç ,是å«`code`还是å«`errCode`?错误内容是`message`还是`errMsg`?内容的国际化如何处ç†ï¼Ÿ - -å¦‚æžœæ²¡æœ‰ä¸€å¥—ç»Ÿä¸€çš„æ ¼å¼ï¼Œåœ¨å®¢æˆ·ç«¯å°†æ— æ³•ç¼–å†™æœ‰æ•ˆçš„ç½‘ç»œæ‹¦æˆªå™¨ï¼Œæ— æ³•ç»Ÿä¸€å¤„ç†é”™è¯¯ã€‚ - -å¦å¤–,如果ä¸åŒçš„æ’件,云端返回的数æ®æ ¼å¼åƒå·®ä¸‡åˆ«ï¼Œé‚£ä½¿ç”¨è€…æ•´åˆè¿™äº›æ’件也会éžå¸¸éº»çƒ¦ã€‚å›½é™…åŒ–æ›´æ— æ³•è½åœ°ã€‚ - -为æ¤DCloud推出了`uniCloudå“应体规范`。 - -为了与uni-appå‰ç«¯çš„APIé”™è¯¯å›žè°ƒé£Žæ ¼ç»Ÿä¸€ï¼ŒuniCloudå“应体规范定义的云端返回信æ¯ï¼ˆå°¤å…¶æ˜¯æŠ¥é”™æ—¶ï¼‰åº”包å«`errCode`å’Œ`errMsg`。 - -除æ¤ä¹‹å¤–å“应体规范还包å«`newToken`å—段,用于token的自动ç»æœŸï¼ˆäº‘对象接收å«æœ‰newTokençš„å“应åŽä¼šè‡ªåŠ¨æ›´æ–°storage内å˜å‚¨çš„`uni_id_token`åŠ`uni_id_token_expired`,æ¤è¡Œä¸ºæ–°å¢žäºŽ`HBuilderX 3.4.13`)。开å‘è€…ä¸€èˆ¬æ— éœ€å…³å¿ƒæ¤æ•°æ®ï¼Œuni-app客户端和云端uni-id之间会自动管ç†tokenåŠç»æœŸã€‚ - -`uniCloudå“应体`示例如下: - -```json -// 失败返回值 -{ - "errCode": 'uni-id-account-banned', - "errMsg": 'è´¦å·è¢«ç¦ç”¨' -} -``` - -```json -// æˆåŠŸè¿”回值 -{ - "errCode": 0, - "errMsg": '登录æˆåŠŸ', - "uid": 'xxx', // å…¶ä»–ä¿¡æ¯ - "newToken": { // 用于下å‘æ–°token给客户端 - "token": 'xxx', - "tokenExpired": 'xxx' - } -} -``` - -HBuilderX内使用代ç å—`returnu`å¯ä»¥å¿«é€Ÿè¾“入以下代ç (`HBuilderX 3.4.0`åŠä»¥ä¸Šç‰ˆæœ¬ï¼‰: - -```js -return { - errCode: 0, - errMsg: '' -} -``` - -- errCode - -errCode在æˆåŠŸæ—¶åº”返回数å—`0`,失败时应返回一个以æ’件id开头的“å—符串â€ï¼Œæ¯ä¸ªå•è¯ä»¥è¿žå—符(`-`)分割。åšå‡ºè¿™æ ·çš„规定是为了防æ¢ä¸åŒæ’件之间出现é‡å¤é”™è¯¯ç - -以`'uni-id-account-banned'`错误ç 为例,`uni-id`为æ’件id,`account-banned`为错误缩写。 - -如果业务开å‘的代ç 并ä¸å‘布æ’件市场,那么为了é¿å…下载了一个市场的æ’件产生冲çªï¼ŒæŽ¨è使用ä¸åŒ…å«â€œ-â€çš„å—符串æ¥åšerrCode(æ’件市场的所有æ’件ID必须包å«â€œ-â€ï¼‰ã€‚ - -åŽç»uniCloud会æä¾›è‡ªåŠ¨æ ¹æ®errCode对errMsg进行国际化处ç†çš„功能,开å‘者仅需ä¿è¯äº‘函数返回值满足`uniCloudå“应体规范`å³å¯ã€‚ - -- errMsg - -errMsg用于å˜æ”¾å…·ä½“错误信æ¯ï¼ŒåŒ…括展示给开å‘者ã€ç»ˆç«¯ç”¨æˆ·çš„é”™è¯¯ä¿¡æ¯ - -## uniCloud API列表 - -äº‘å‡½æ•°æ”¯æŒ js å’Œ nodejs çš„æ ‡å‡†API,如`console.log()`ã€`setTimeout()`,å¦è§[nodejs官网](https://nodejs.org/en/docs/)。nodejs版本,详è§[云函数è¿è¡ŒçŽ¯å¢ƒ](?id=runtime) - -é™¤äº†æ ‡å‡†API外,云函数环境ä¸å†…置了`uniCloud`对象,扩展了一批新API,实际开å‘ä¸æ›´å¸¸ç”¨çš„是uniCloud的扩展API。è§ä¸‹ï¼š - -|API |æè¿° | -|-- |-- | -|uniCloud.database() |云数æ®åº“对象 [详情](uniCloud/cf-database.md) | -|uniCloud.databaseJQL() |云函数ä¸ä½¿ç”¨JQLè¯æ³•æ“作数æ®åº“ [详è§](uniCloud/jql-cloud.md)ï¼Œéœ€æ·»åŠ æ‰©å±•åº“ | -|uniCloud.redis() |使用redis [详è§](uniCloud/redis.md)ï¼Œéœ€æ·»åŠ æ‰©å±•åº“ -|uniCloud.uploadFile() |äº‘å‡½æ•°ä¸Šä¼ æ–‡ä»¶åˆ°äº‘å˜å‚¨ [详情](uniCloud/storage?id=clouduploadfile) | -|uniCloud.downloadFile() |云函数下载云å˜å‚¨çš„文件到云函数è¿è¡ŒçŽ¯å¢ƒ [详情](uniCloud/storage?id=clouddownloadfile) | -|uniCloud.deleteFile() |äº‘å‡½æ•°åˆ é™¤äº‘å˜å‚¨çš„文件 [详情](uniCloud/storage?id=clouddeletefile) | -|uniCloud.getTempFileURL() |获å–云å˜å‚¨æ–‡ä»¶çš„临时路径 [详情](uniCloud/storage?id=cloudgettempfileurl) | -|uniCloud.customAuth() |使用云厂商自定义登录,仅腾讯云支æŒ[详情](uniCloud/authentication.md?id=cloud-custom-auth) | -|uniCloud.callFunction() |云函数/云对象ä¸è°ƒç”¨å¦ä¸€ä¸ªäº‘函数 [è§ä¸‹](#callbyfunction) | -|uniCloud.importObject() |云函数/云对象ä¸è°ƒç”¨å¦ä¸€ä¸ªäº‘对象 [详情](cloud-obj.md?id=call-by-cloud) | -|uniCloud.httpclient |云函数ä¸é€šè¿‡http访问其他系统 [è§ä¸‹](#httpclient) | -|uniCloud.httpProxyForEip |使用云厂商代ç†è®¿é—®httpæœåŠ¡ï¼ˆé˜¿é‡Œäº‘的解决微信需è¦å›ºå®šIPçš„æ–¹æ¡ˆï¼‰ï¼Œä»…é˜¿é‡Œäº‘äº‘ç«¯çŽ¯å¢ƒæ”¯æŒ [详è§](#aliyun-eip),新增于`HBuilderX 3.5.5`| -|uniCloud.sendSms() |å‘é€çŸä¿¡ï¼Œéœ€æ·»åŠ 扩展库 [详è§](uniCloud/send-sms.md) | -|uniCloud.getPhoneNumber() |获å–一键登录手机å·ï¼Œéœ€æ·»åŠ 扩展库 [详è§](uniCloud/univerify.md?id=cloud) | -|uniCloud.init() |获å–指定æœåŠ¡ç©ºé—´çš„uniCloud实例 [详è§](uniCloud/concepts/space.md?id=multi-space) | -|uniCloud.logger |云函数ä¸æ‰“å°æ—¥å¿—到[uniCloud web控制å°](https://unicloud.dcloud.net.cn/)的日志系统(éžHBuilderX控制å°ï¼‰[详情](rundebug.md?id=uniCloudlogger) | -|uniCloud.getRequestList |获å–当å‰äº‘函数实例内æ£åœ¨å¤„ç†çš„请求Id列表 [详è§](#get-request-list),新增于`HBuilderX 3.5.5`| -|uniCloud.getClientInfos |获å–当å‰äº‘函数实例内æ£åœ¨å¤„ç†çš„请求对应的客户端信æ¯åˆ—表 [详è§](#get-client-infos),新增于`HBuilderX 3.5.5`| -|uniCloud.getCloudInfos |获å–当å‰äº‘函数实例内æ£åœ¨å¤„ç†çš„请求对应的云端信æ¯åˆ—表 [详è§](#get-cloud-infos),新增于`HBuilderX 3.5.5`| - -## 错误对象@uni-cloud-error - -云函数调用uniCloud接å£æ—¶ï¼ˆåŒ…括请求云函数ã€äº‘对象ã€äº‘å˜å‚¨ç‰ï¼‰å¯èƒ½å˜åœ¨æŠ›å‡ºé”™è¯¯çš„场景,æ¤æ—¶ä¼šæŠ›å‡ºuniCloudæ ‡å‡†çš„é”™è¯¯å¯¹è±¡ï¼ˆä»¥ä¸‹è®°ä¸ºuniCloudError),uniCloudError包å«ä»¥ä¸‹å±žæ€§ - -|属性 |类型 |必备 |说明 | -|-- |-- |-- |-- | -|errCode |string |是 |错误ç | -|errMsg |string |是 |é”™è¯¯ä¿¡æ¯ | -|requestId |string |å¦ |请求Id,用于排查错误 | -|detail |object |å¦ |仅云对象主动返回错误对应的å“应体规范时会有æ¤å±žæ€§ | - -å¦å¤–uniCloudError对象上还有code属性和message属性,两者å‡ä¸æŽ¨è使用。 - -## 访问数æ®åº“ - -云函数ä¸æ”¯æŒè®¿é—®æœ¬æœåŠ¡ç©ºé—´ä¸‹çš„ã€æˆ–ç»æŽˆæƒçš„其他æœåŠ¡ç©ºé—´ä¸‹çš„,数æ®åº“。 - -- 使用 MongoDB è¯æ³•æ“作数æ®åº“,å¦è§[文档](uniCloud/cf-database.md) -- 使用 JQL è¯æ³•æ“作数æ®åº“,å¦è§[文档](uniCloud/jql-cloud.md) - -## 访问其他HTTPæœåŠ¡@httpclient - -云函数ä¸å¦‚需è¦è¯·æ±‚其他httpæœåŠ¡ï¼Œåˆ™ä½¿ç”¨`uniCloud.httpclient`ã€‚æ— éœ€é¢å¤–ä¾èµ–,就å¯ä»¥è¯·æ±‚任何 HTTP å’Œ HTTPS å议的 Web æœåŠ¡ã€‚`uniCloud.httpclient`返回的是一个[urllib实例](https://github.com/node-modules/urllib)。 - -**uniCloud.httpclient.request(URL,requestOptions)** - -**requestOptionså‚数说明** - -|å‚æ•°å |类型 |是å¦å¿…å¡« |默认值 |说明 | -|---- |---- |---- |---- |---- | -|method |String | - |GET |HTTP 请求方法, 默认为:GET. å¯é€‰å€¼ï¼š GET, POST, DELETE, PUT | -|data |Object | - |- |å‘é€çš„æ•°æ® | -|dataAsQueryString |Boolean | - |true |是å¦å¼ºåˆ¶è½¬æ¢data为queryString | -|content |String | Buffer | - |- |手动设置请求的payload,设置åŽä¼šå¿½ç•¥data | -|stream |ReadStream |- |- |å‘é€è¯·æ±‚æ£æ–‡çš„å¯è¯»æ•°æ®æµ | -|writeStream |WriteStream |- |- |接å—å“应数æ®çš„å¯å†™æ•°æ®æµ | -|consumeWriteStream |Boolean |- |true |是å¦ç‰å¾… writeStream 完全写完æ‰ç®—å“应全部接收完毕 | -|files |Array<ReadStream|Buffer|String> | Object | ReadStream | Buffer | String| - |- |ä¸Šä¼ çš„æ–‡ä»¶ï¼Œè®¾ç½®åŽå°†ä¼šä½¿ç”¨ multipart/form-data æ ¼å¼ã€‚如果未设置method,将会自动将method设置为POST | -|contentType |String | - |- |ä¸Šä¼ æ•°æ®çš„æ ¼å¼ï¼Œè®¾ä¸º`json`会自动在`header`内设置`Content-Type: application/json` | -|nestedQuerystring |Boolean | - |- |转æ¢data为queryString时默认ä¸æ”¯æŒåµŒå¥—Object,æ¤é€‰é¡¹è®¾ç½®ä¸ºtrue则支æŒè½¬æ¢åµŒå¥—Object | -|dataType |String | - |- |返回的数æ®æ ¼å¼ï¼Œå¯é€‰å€¼ä¸º 'json'(返回数æ®è½¬ä¸ºJSON),'text'(返回数æ®è½¬ä¸ºå—符串), ''(返回数æ®ä¸åšå¤„ç†ï¼Œé»˜è®¤å€¼ï¼‰ | -|fixJSONCtlChars |Boolean |- |false |在JSON.parse之å‰å¤„ç†å“应结果ä¸çš„控制å—符(Control Character) | -|headers |Object | - |- |请求头 | -|timeout |Number | Array | - |5000 |超时时间设置。设置为数组时第一项为请求超时,第二项为返回超时。设置为数å—时相当于åŒæ—¶è®¾ç½®è¯·æ±‚超时和返回超时,å³`timeout:3000`效果ç‰äºŽ`timeouut:[3000,3000]` | -|auth |String |- |- |简å•ç™»å½•æŽˆæƒï¼ˆBasic Authentication)å‚数,必须按照 `user:password` æ ¼å¼è®¾ç½® | -|digestAuth |String |- |- |摘è¦ç™»å½•æŽˆæƒï¼ˆDigest Authentication)å‚数,必须按照 `user:password` æ ¼å¼è®¾ç½® | -|agent |[http.Agent](https://nodejs.org/api/http.html#http_class_http_agent) |- |- |http代ç†ï¼Œå¦‚ä¸ä½¿ç”¨å¯è®¾ä¸ºfalse | -|httpsAgent |[https.Agent](https://nodejs.org/api/https.html#https_class_https_agent) |- |- |https代ç†ï¼Œå¦‚ä¸ä½¿ç”¨å¯è®¾ä¸ºfalse | -|ca |String|Buffer|Array |- |- |è¯ä¹¦å†…容 | -|rejectUnauthorized |Boolean |- |true |是å¦åœ¨è¯ä¹¦ä¸å—信任时返回错误 | -|pfx |String|Buffer |- |- |包å«äº†ç§é’¥, è¯ä¹¦å’ŒCA certs, 一般是 PFX 或者 PKCS12 æ ¼å¼ | -|key |String|Buffer |- |- |PEFæ ¼å¼çš„æœåŠ¡å™¨çš„ç§é’¥ | -|cert |String|Buffer |- |- |PEMæ ¼å¼çš„æœåŠ¡å™¨è¯ä¹¦å¯†é’¥ | -|passphrase |String |- |- |ç§é’¥æˆ–pfx密ç çš„å—符串 | -|ciphers |String |- |- |使用或排除的cipher | -|secureProtocol |String |- |- |SSL 使用的方法,例如,`SSLv3_method` 强制 SSL 版本为3。 | -|followRedirect |Boolean |- |false |收到3xxå“应时是å¦è‡ªåŠ¨é‡å®šå‘ | -|maxRedirects |Number |- |10 |最高é‡å®šå‘次数 | -|formatRedirectUrl |Function |- |- |æ‰‹åŠ¨æ ¼å¼åŒ–url | -|beforeRequest |Function |- |- |请求å‘é€å‰çš„é’©å | -|streaming |Boolean |- |false |是å¦ç›´æŽ¥è¿”回å“应æµï¼Œå¼€å¯ streaming 之åŽï¼ŒHttpClient 会在拿到å“应对象 res 之åŽé©¬ä¸Šè¿”回, æ¤æ—¶ result.headers å’Œ result.status å·²ç»å¯ä»¥è¯»å–到,åªæ˜¯æ²¡æœ‰è¯»å– data æ•°æ®è€Œå·²ã€‚| -|gzip |Boolean |- |false |是å¦æ”¯æŒ gzip å“åº”æ ¼å¼ã€‚å¼€å¯ gzip 之åŽï¼ŒHttpClient 将自动设置 Accept-Encoding: gzip 请求头, 并且会自动解压带 Content-Encoding: gzip å“应头的数æ®ã€‚ | -|timing |Boolean |- |false |是å¦å¼€å¯è¯·æ±‚å„é˜¶æ®µçš„æ—¶é—´æµ‹é‡ | -|enableProxy |Boolean |- |false |是å¦å¯ç”¨ä»£ç† | -|proxy |String |- |null | 代ç†åœ°å€ | -|lookup |Function |- |- |自定义DNS查询函数 | -|checkAddress |Function |- |- |æ ¡éªŒè¯·æ±‚åœ°å€ | -|trace |Boolean |- |false |是å¦å¯ç”¨æ•èŽ·å †æ ˆ | - -**注æ„** - -默认情况下request接å£ä¸ä¼šå¤„ç†è¿”回的数æ®ï¼Œå³ä¸ä¼ `dataType`å‚数时会返回buffer类型的数æ®ï¼Œå¦‚需自动解æžjsonæ ¼å¼çš„返回结果,需è¦å°†`dataType`设置为`"json"` - -**示例代ç ** - -```js -const res = await uniCloud.httpclient.request(apiUrl, { - method: 'POST', - data: { - test: 'testValue' - }, - contentType: 'json', // 指定以application/jsonå‘é€dataå†…çš„æ•°æ® - dataType: 'json' // 指定返回值为jsonæ ¼å¼ï¼Œè‡ªåŠ¨è¿›è¡Œparse - }) -console.log(res) -``` - -返回数æ®ç»“构如下 - -```js -{ - "data": {"name": "DCloud"}, // å“应内容 - "status": 200, // 状æ€ç - "headers": { // å“应头,仅作示例,ä¸åŒæœåŠ¡å™¨è¿”回的有差异 - "date": "Tue, 29 Dec 2020 08:10:30 GMT", - "content-type": "application/json", - "content-length": "276", - "connection": "keep-alive", - "server": "gunicorn/19.9.0", - "access-control-allow-origin": "*", - "access-control-allow-credentials": "true" - } -} - -``` - -### å‘é€formdataç±»åž‹æ•°æ® - -实际业务ä¸å¸¸æœ‰ä½¿ç”¨äº‘函数å‘é€formdata类型数æ®çš„需求,比如微信å°ç¨‹åºæ供的一些æœåŠ¡ç«¯æŽ¥å£ï¼ˆå›¾ç‰‡å†…容安全检测ã€è¯†åˆ«å›¾ç‰‡äºŒç»´ç ç‰ï¼‰ï¼Œå¯ä»¥å‚考以下示例进行å‘é€ - -```js -'use strict'; -const fs = require('fs') -const path = require('path') -const FormData = require('form-data'); // æ¤form-data需è¦ä½¿ç”¨npm安装,地å€ï¼šhttps://www.npmjs.com/package/form-data -exports.main = async (event, context) => { - const form = new FormData() - form.append('media', fs.readFileSync(path.resolve(__dirname, './test.jpg')), { // 为方便演示æ¤å¤„直接使用云函数目录下的test.jpg文件 - filename: 'test.jpg', - contentType: 'image/jpeg' - }); - form.append('otherParam', 'otherParam content'); - const res = await uniCloud.httpclient.request('https://httpbin.org/post', { - method: 'POST', - content: form.getBuffer(), // 请求内容 - headers: form.getHeaders(), // 请求头 - dataType: 'json' // æ¤å¤„指定为json表示将æ¤è¯·æ±‚的返回值解æžä¸ºjson - }) - return res -}; - -``` - -## 请求和环境API - -由于å˜åœ¨[å•å®žä¾‹å¤šå¹¶å‘](#concurrency)的情况,实例级的uniCloud对象,和æ¯ä¸ªè¯·æ±‚request是一对多的关系。 - -è¿™ä¹Ÿé€ æˆäº†ä¸Žè¯·æ±‚相关的上下文,比如客户端信æ¯ï¼Œéœ€è¦é€šè¿‡è¯·æ±‚æ¥èŽ·å–。 - -为了更好的管ç†è¯·æ±‚和请求相关的上下文,uniCloudæ供了下é¢ä¸€æ‰¹API。 - -### 获å–请求id列表@get-request-list - -**示例** - -```js -uniCloud.getRequestList() -// 返回值:['3228166e-3c17-4d58-9707-xxxxxxxx'] -``` - -如没有é…ç½®[å•å®žä¾‹å¤šå¹¶å‘](#concurrency),数组里åªä¼šè¿”回一项内容。é…ç½®åŽå¯èƒ½ä¼šå¤šé¡¹ï¼Œæ£åœ¨å¹¶å‘的所有请求的requestId都会返回。 - -当返回多项时,在uniCloudå¯¹è±¡ä¸Šæ— æ³•æ˜Žç¡®å½“å‰è¯·æ±‚是数组ä¸çš„哪一个。所以æ供了其他方法æ¥èŽ·å–当å‰è¯·æ±‚: -- 云对象通过`this.getUniCloudRequestId()`。[详情](cloud-obj.md#get-request-id) -- 云函数通过函数自带å‚æ•°context。[详情](cf-callfunction.md#context) - -### 获å–客户端信æ¯åˆ—表#get-client-infos - -åŒç†ï¼Œè€ƒè™‘到å•å®žä¾‹å¤šå¹¶å‘,`uniCloud.getClientInfos()`获å–客户端信æ¯ä¹Ÿæ˜¯ä¸€ä¸ªæ•°ç»„。 - -```js -const clientInfos = uniCloud.getClientInfos() -``` - -返回值 -```js -clientInfos = [{ - appId: '__UNI_xxxxx', - requestId: '3228166e-3c17-4d58-9707-xxxxxxxx' - // ... -}] -``` - -如未开å¯å•å®žä¾‹å¤šå¹¶å‘,那么数组åªæœ‰1项。å•å®žä¾‹å¤šå¹¶å‘场景下返回æ£åœ¨å¹¶å‘的所有请求的客户端信æ¯åˆ—表。 - -**返回值** - -getClientInfos返回的信æ¯ï¼Œæ˜¯åœ¨å®¢æˆ·ç«¯çš„[uni.getSystemInfo](/api/system/info.md#getsysteminfo)çš„åŸºç¡€ä¹‹ä¸Šï¼Œå¢žåŠ äº†ä¸€äº›é¢å¤–çš„ä¿¡æ¯ã€‚ - -除了`getSystemInfo`返回å—段外,还包å«ä»¥ä¸‹ä¿¡æ¯ - -|属性å |类型 |说明 | -|-- |-- |-- | -|requestId|string |请求Id,å¯ä»¥ä½¿ç”¨æ¤å—段ç›é€‰å‡ºå½“å‰è¯·æ±‚çš„å®¢æˆ·ç«¯ä¿¡æ¯ | -|clientIP |string |客户端ip | -|userAgent|string |客户端ua,注æ„éžæœ¬åœ°è¿è¡ŒçŽ¯å¢ƒä¸‹å®¢æˆ·ç«¯getSystemInfoSync也会获å–uaå‚æ•°å¹¶ä¸Šä¼ ç»™äº‘å¯¹è±¡ï¼Œä½†æ˜¯äº‘å¯¹è±¡ä¼šä»Žhttp请求头里é¢èŽ·å–ua而ä¸æ˜¯clientInfo里é¢çš„ua| -|source |string |调用æ¥æºï¼Œè¿”回值è§ä¸‹ã€‚ | -|scene |string |场景值。客户端[uni.getLaunchOptionsSync](/api/plugins/getLaunchOptionsSync.md#getlaunchoptionssync)返回的sceneå‚数, | - -云函数调用æ¥æºsource,它的值域为: - -|å–值 |说明 | -|-- |-- | -|client |uni-app客户端导入云对象调用 | -|function |由其他云函数或云对象调用 | -|http |云对象URL化åŽé€šè¿‡http访问调用| -|timing |定时任务调用云对象 | - -**注æ„事项** - -- 客户端上报的信æ¯åœ¨ç†è®ºä¸Šå˜åœ¨è¢«ç¯¡æ”¹å¯èƒ½ï¼Œå®žé™…业务ä¸åº”验è¯å‰ç«¯ä¼ æ¥çš„æ•°æ®çš„åˆæ³•æ€§ -- 除了clientIP外,其他客户端信æ¯åªæœ‰ä½¿ç”¨uni-app客户端以callFunction或者importObjectæ–¹å¼è®¿é—®äº‘函数或云对象时æ‰æœ‰ -- 云对象与云函数内获å–客户端platformç¨æœ‰ä¸åŒï¼Œäº‘函数未拉é½vue2ã€vue3版本appå¹³å°çš„platform值,vue2为`app-plus`,vue3为`app`ã€‚äº‘å¯¹è±¡æ— è®ºå®¢æˆ·ç«¯æ˜¯vue2还是vue3,在appå¹³å°èŽ·å–çš„platformå‡ä¸º`app`。这一点在使用uni-id时需è¦ç‰¹åˆ«æ³¨æ„,详情è§ï¼š[uni-id文档 preferedAppPlatform](uniCloud/uni-id.md?id=prefered-app-platform) - -除了`uniCloud.getClientInfos()`API,在云函数context和云对象thisä¸ï¼Œä¹Ÿå¯ä»¥ç›´æŽ¥èŽ·å–当å‰å®¢æˆ·ç«¯ä¿¡æ¯ã€‚ -- 云对象通过`this.getClientInfo()`。[详情](cloud-obj.md#get-client-info) -- 云函数通过函数自带å‚æ•°context。[详情](cf-callfunction.md#context) - -### 获å–云端信æ¯@get-cloud-infos - -åŒä¸Šï¼Œä¸ºäº†å…¼å®¹å¹¶å‘场景,获å–云端信æ¯`uniCloud.getCloudInfos()`返回的也是数组。 - -**示例** - -```js -const cloudInfos = uniCloud.getCloudInfos() -cloudInfos = [{ - provider: 'aliyun', - spaceId: 'xxxxx', - functionName: 'xxx', - functionType: 'xxxx', - requestId: '3228166e-3c17-4d58-9707-xxxxxxxx' -}] -``` - -**返回值** - -|å‚æ•°å |类型 |必备 |说明 | -|-- |-- |-- |-- | -|provider |string |是 |æœåŠ¡ç©ºé—´ä¾›åº”商,阿里云为:`aliyun`,腾讯云为:`tencent`| -|spaceId |string |是 |æœåŠ¡ç©ºé—´Id | -|functionName |string |是 |云函数å称 | -|functionType |string |是 |云对象为`cloudobject`ã€äº‘函数为`cloudfunction` | -|requestId |string |是 |请求Id,å¯ä»¥ä½¿ç”¨æ¤å—段ç›é€‰å‡ºå½“å‰è¯·æ±‚çš„äº‘ç«¯ä¿¡æ¯ | - -除了`uniCloud.getCloudInfos()`API,在云函数context和云对象thisä¸ï¼Œä¹Ÿå¯ä»¥ç›´æŽ¥èŽ·å–当å‰è¯·æ±‚的云端信æ¯ã€‚ -- 云对象通过`this.getCloudInfo()`。[详情](cloud-obj.md#get-cloud-info) -- 云函数通过函数自带å‚æ•°context。[详情](cf-callfunction.md#context) - - -上述3个APIï¼Œéƒ½å› ä¸ºå•å®žä¾‹å¤šå¹¶å‘而被设计æˆæ•°ç»„æ–¹å¼ã€‚实际上,大多数开å‘者并ä¸ä½¿ç”¨å•å®žä¾‹å¤šå¹¶å‘。 - -在ä¸è€ƒè™‘å•å®žä¾‹å¤šå¹¶å‘时,也å¯ä»¥ç›´æŽ¥ä½¿ç”¨uniCloudçš„getRequestListã€getClientInfosã€getCloudInfos方法ä¸ç¬¬ä¸€ä¸ªæ•°ç»„项。 - -或者在云对象的this和云函数的context里获å–相关上下文信æ¯ä¹Ÿå¯ä»¥ã€‚ - - -## 扩展库@extension - -uniCloudçš„apiä¸ï¼Œæœ‰äº›api对应的实现,其代ç 体积较大,且这些功能并ä¸æ˜¯æ¯ä¸€ä¸ªäº‘函数都会使用。为了方便开å‘者控制云函数的体积,设计了`uniCloud扩展库`的概念。 - -å¼€å‘者å¯ä»¥å¯¹äº‘函数目录点å³é”®ï¼Œç®¡ç†å…¬å…±æ¨¡å—和扩展库ä¾èµ–,在其ä¸é€‰æ‹©è¦åŠ 载的扩展库。这个å¯è§†åŒ–ç•Œé¢å¯¹åº”çš„æ•°æ®åœ¨äº‘函数目录下的 package.json 内的`extensions`å—段下。 - -注æ„:未引用扩展库的,使用uniCloud相应api时会报错。 - - -**ç›®å‰æ”¯æŒçš„扩展库如下** - -- JQL扩展库[uni-cloud-jql]:用于在云函数内使用JQLè¯æ³•æ“作数æ®åº“,详è§ï¼š[JQL扩展库](uniCloud/jql-cloud.md) -- redis扩展库[uni-cloud-redis]:云函数内使用redis,详è§ï¼š[redis扩展库](uniCloud/redis.md) -- å‘é€çŸä¿¡æ‰©å±•[uni-cloud-sms]:云函数ä¸å‘é€çŸä¿¡ï¼Œè¯¦è§ï¼š[sms扩展](uniCloud/send-sms?id=extension) -- 一键登录API扩展[uni-cloud-verify]:手机App调用è¿è¥å•†ä¸€é”®ç™»é™†æœåŠ¡æ—¶ï¼Œäº‘函数ä¸èŽ·å–到真实手机å·ï¼Œ 详è§ï¼š[一键登陆扩展库](uniCloud/univerify?id=extension) -- 统一推é€æœåŠ¡æ‰©å±•åº“[uni-cloud-push]:云函数内使用uni-push,详è§ï¼š[uniCloud/uni-cloud-push/api] - -以下是一个开å¯äº†redis扩展库的云函数package.json示例,注æ„æ¤æ–‡ä»¶ä¸æ”¯æŒæ³¨é‡Šï¼Œä¸‹æ–¹ç¤ºä¾‹ä¸çš„注释仅为演示 - -```js -{ - "name": "add-article", - "version": "1.0.0", - "description": "æ–°å¢žæ–‡ç« ", - "main": "index.js", - "extensions": { - "uni-cloud-redis": {} // é…置为空对象å³å¯ï¼ŒåŽç»å¦‚有扩展å‚数会在æ¤å¤„é…ç½® - } -} -``` - -## 公共模å—@common - -云函数支æŒå…¬å…±æ¨¡å—。多个云函数的共享部分,å¯ä»¥æŠ½ç¦»ä¸ºå…¬å…±æ¨¡å—,然åŽè¢«å¤šä¸ªäº‘函数引用。由于篇幅较长,[详è§](uniCloud/cf-common) - -## 使用npm - -云函数的è¿è¡ŒçŽ¯å¢ƒæ˜¯ `Node.js`ï¼Œå› æ¤æˆ‘们å¯ä»¥ä½¿ç”¨ `npm` 安装第三方ä¾èµ–。 - -注æ„:阿里云目å‰ä»…支æŒå…¨é‡ä¸Šä¼ 云函数(整个 node_modulesæ–‡ä»¶å¤¹å…¨éƒ¨ä¸Šä¼ ï¼‰ï¼Œå› æ¤æ醒开å‘者精简ä¾èµ–,å¦åˆ™å¯èƒ½ä¼šæ¯æ¬¡ä¸Šä¼ 时间很慢,影å“å¼€å‘体验。并且太大的npm库影å“云函数的è¿è¡Œæ€§èƒ½ã€‚ - -è…¾è®¯äº‘ä¼šåœ¨ä¸Šä¼ äº‘å‡½æ•°åŽè‡ªåŠ¨å®‰è£…需è¦çš„npmä¾èµ–。 - -Tips: -- ç›®å‰æ¯ä¸ªäº‘å‡½æ•°ä¸Šä¼ åŒ…å¤§å°é™åˆ¶ä¸º10M。如果npmåŒ…å¾ˆå¤§ï¼Œé˜¿é‡Œäº‘çš„æ•´ä½“ä¸Šä¼ æœºåˆ¶ä¼šæ— æ³•æ»¡è¶³éœ€æ±‚ã€‚æ¤æ—¶åªèƒ½é€‰æ‹©è…¾è®¯äº‘,交给腾讯云自动安装ä¾èµ–。 - - -## 云函数/云对象ä¸è°ƒç”¨äº‘函数@callbyfunction - -### 调用三方云函数或云对象 - -用法åŒå®¢æˆ·ç«¯è°ƒç”¨äº‘函数,ä»ç„¶æ˜¯`uniCloud.callfunction`,但ä¸æ”¯æŒcallbackå½¢å¼ã€‚ - -**请求å‚æ•°** - -|å—段 |类型 |å¿…å¡« |说明 | -|--- |--- |--- |--- | -|name |String |是 |云函数å称。 | -|data |Object |å¦ |云函数å‚数。 | - -**å“应å‚æ•°** - -|å—段 |类型 |必备 |说明 | -|--- |--- |--- |--- | -|errCode |String |å¦ |状æ€ç ,æ“作æˆåŠŸåˆ™ä¸è¿”回。 | -|errMsg |String |å¦ |错误æ述。 | -|result |Object |å¦ |云函数执行结果。 | -|requestId|String |å¦ |请求åºåˆ—å·ï¼Œç”¨äºŽé”™è¯¯æŽ’查。 | - -**示例代ç ** - -```javascript -let callFunctionResult = await uniCloud.callFunction({ - name: "test", - data: { a: 1 } -}) -``` - -**注æ„** - -由于调用方ä¸æ˜¯uni-app客户端,云函数的contextã€äº‘对象的this.getClientInfoç‰APIæ— æ³•èŽ·å–客户端信æ¯ï¼ŒåŒ…括 uni-id-token。 - -å¯ä»¥åœ¨äº‘å‡½æ•°äº’è°ƒæ—¶æ‰‹åŠ¨ä¼ é€’ token ï¼Œæˆ–è€…æ ¡éªŒè°ƒç”¨æ¥æºï¼ˆsource)为云函数(function)时ä¸éªŒè¯ç”¨æˆ· token。 - -云函数/云对象互相调用时调用方会通过公网访问被调用方,访问速度ä¸å¦‚直接将逻辑放在调用方执行。使用å‰è¯·ç¡®ä¿ä½ 确实需è¦æ¤åŠŸèƒ½ã€‚ - -`HBuilderX 3.4.0`版本之å‰**云函数å³é”®æœ¬åœ°è¿è¡Œæ—¶**,里é¢çš„代ç å†æ¬¡callFunction会调用云端的云函数而ä¸æ˜¯æœ¬åœ°äº‘函数,æ¤bugåŽç»ç‰ˆæœ¬å·²ä¿®å¤ã€‚ - -### 云函数递归调用自身@recurrence - -除了调用三方云函数,事实上云函数还å¯ä»¥é€’归调用自己。 - -当一个云函数实例的资æºä¸èƒ½æ»¡è¶³éœ€æ±‚,或超时时间ä¸å¤Ÿç”¨æ—¶ã€‚比如è¦ç»™10万个用户å‘é€çŸä¿¡ï¼Œè€ŒçŸä¿¡å‘é€æŽ¥å£ä¸€æ¬¡è°ƒç”¨æœ€å¤šæ”¯æŒ50个手机å·ç ï¼Œè¿™æ ·æœ€å°‘éœ€è¦è°ƒç”¨2000次接å£æ‰èƒ½å®Œæˆï¼›è€Œä¸€ä¸ªäº‘函数实例完æˆä¸äº†2000次接å£çš„调用。这ç§åœºæ™¯å°±å¯ä»¥ä½¿ç”¨äº‘函数递归调用,分解任务实现。 - -示例代ç 如下: - -```js -// 当å‰äº‘函数å称 send-sms-cf -'use strict'; -const db = uniCloud.database(); -const dbCmd = db.command -const userTable = db.collection('uni-id-users') -exports.main = async (event, context) => { - //执行业务逻辑 - let res = await sendSms(event.before_id) - if (res.errCode) { - return res - }else{ - // 如果没有报错,就让当å‰äº‘函数 调用当å‰äº‘函数(云对象åŒç†ï¼‰ã€‚注æ„:这里是异æ¥çš„ - uniCloud.callFunction({ - name: 'send-sms-cf', - data: { - before_id: res.before_id - } - }).catch(e=>{ - console.log(e.message); - }).then(e=>{ - console.log(e.result); - }) - - // ç‰å¾…500毫秒,给一个请求å‘出去的时间 - return await new Promise((resolve, reject) => { - setTimeout(() => { - resolve(res) - }, 500) - }) - } - - async function sendSms(before_id) { - console.log('before_id',before_id); - let where = { - phone: dbCmd.exists(true), - //..这里å¯ä»¥å†™ä½ 自己的其他æ¡ä»¶ï¼Œå¦‚超过多久没登录的用户 last_login_date < Date.now() - 3600*24*... - } - if(before_id){ - //高性能分页查询,以上一次查询的最åŽä¸€æ¡æ•°æ®çš„id被起始id - where._id = dbCmd.gt(before_id) - } - - let res = await userTable.where(where) - .limit(50) - .orderBy("_id", "asc") - .get() - - if (!res.data.length) { - return { - errCode: 'sendSms-invalid', - errMsg: '结æŸï¼Œæ²¡æœ‰ç¬¦åˆæ¡ä»¶çš„接收者' - } - } - let phoneList = res.data.map(item => item.phone) - res = await uniCloud.sendSms({ - phoneList, - appid: '__UNI__xxxxxxx', - smsKey: '****************', - smsSecret: '****************', - templateId: '100**', // 请替æ¢ä¸ºè‡ªå·±ç”³è¯·çš„模æ¿id - data: { - text1: 'xxx', - text2: 'xxx' - } - }) - if (res.errCode) { - return res - } - return { - errCode: 0, - before_id: res.data[res.data.length - 1]._id - } - } -}; -``` - -注æ„:如果ä¸å°å¿ƒæŠŠé€’归云函数写æˆæ»å¾ªçŽ¯ï¼Œå°±æŠŠäº‘å‡½æ•°çš„å†…å®¹å…¨éƒ¨åˆ é™¤ï¼Œé‡æ–°ä¸Šä¼ 覆盖å³å¯ - - -### 云函数内访问其他æœåŠ¡ç©ºé—´@call-by-function-cross-space - -> ä»…è…¾è®¯äº‘æ”¯æŒ - -在腾讯云æœåŠ¡ç©ºé—´çš„云函数内支æŒèŽ·å–**åŒè´¦å·**下其他æœåŠ¡ç©ºé—´çš„uniCloud实例,å‚考:[一个应用访问多个æœåŠ¡ç©ºé—´](uniCloud/concepts/space.md?id=multi-space),并使用æ¤å®žä¾‹è°ƒç”¨å¯¹åº”æœåŠ¡ç©ºé—´çš„云函数。 - -```javascript -//å¼€å‘者创建了多个æœåŠ¡ç©ºé—´ï¼Œåˆ™éœ€æ‰‹åŠ¨åˆå§‹åŒ–。注æ„这是å‰ç«¯ä»£ç ,ä¸æ˜¯äº‘函数代ç -const myCloud = uniCloud.init({ - provider: 'tencent', - spaceId: 'xxxx-yyy' -}); -//通过uniCloud实例调用云开å‘çš„API -myCloud.callFunction() -myCloud.uploadFile() -``` - -**注æ„** - -- 连接本地云函数调试时,如果å˜åœ¨è·¨æœåŠ¡ç©ºé—´è°ƒç”¨ï¼Œåˆ™callFunction会使用云端云函数 - -## serverless环境说明@runtime - -serverless是动æ€åˆ†åˆ«è®¡ç®—资æºçš„,由æ¤ä¼šå¼•å‘的出一批特有概念:冷å¯åŠ¨ã€å®žä¾‹ã€å¹¶å‘请求ã€æ— 状æ€ã€ä¼ªå…¨å±€å˜é‡ã€‚ - -### 云函数冷å¯åŠ¨ã€çƒå¯åŠ¨@launchtype - -基于云函数按需执行的特点, 函数在ä¸è¢«è§¦å‘的时候, 计算资æºæ˜¯ä¸è¢«æ¿€æ´»çš„。 - -当一个云函数åˆæ¬¡è¢«è§¦å‘时,其完整过程如下: - -1. severless实例化计算实例 -2. åŠ è½½å‡½æ•°ä»£ç -3. å¯åŠ¨ node -4. 执行云函数代ç - -函数被调用时,执行这些完整æ¥éª¤çš„过程称作`冷å¯åŠ¨`, 冷å¯åŠ¨çš„耗时一般在一秒左å³ã€‚ - -一个云函数实例冷å¯åŠ¨åŽï¼Œserverless调度ä¸å¿ƒä¼šä¿ç•™è¿™ä¸ªå®žä¾‹ä¸€å®šæ—¶é—´ã€‚在实例ä¿ç•™æœŸé—´ï¼Œå®¢æˆ·ç«¯å†æ¬¡è¯·æ±‚云函数,ä¸ä¼šè§¦å‘冷å¯åŠ¨ï¼Œé€Ÿåº¦ä¼šæ›´å¿«ã€‚实例的详细定义[è§ä¸‹](#instance) - -云函数实例和执行进程都被å¤ç”¨çš„情况下称之为`çƒå¯åŠ¨`, çƒå¯åŠ¨æ€§èƒ½è¦å¥½éžå¸¸å¤šï¼Œå› 为它åªæœ‰ä¸€ä¸ªæ¥éª¤ï¼š -1. 执行云函数代ç - -如果一个云函数实例长时间没有被å†æ¬¡è°ƒç”¨ï¼Œåˆ™è¯¥è®¡ç®—实例会被**回收**ï¼›åŽç»å†æ¬¡è°ƒç”¨è¯¥äº‘函数时,就会å†æ¬¡è§¦å‘云函数的**冷å¯åŠ¨**。 - -ä¸åŒäº‘厂商的函数实例回收时间ä¸åŒï¼š -- 阿里云:15分钟内没有第二次访问的云函数,就会被回收 -- 腾讯云:30分钟 - -直观的体验表现为:隔了很久ä¸ç”¨çš„云函数,第一次用就会比较慢,然åŽç«‹å³è®¿é—®ç¬¬äºŒæ¬¡ï¼Œåˆ™å¾ˆå¿«ï¼Œæ¯«ç§’级å“应。 - -注:冷å¯åŠ¨è™½æ…¢ä½†ä¹Ÿä¸ä¼šè¶…过1.5秒,如超过1.5秒应该是云函数写的有问题或网络有问题。 - -两家云厂商ä»ç„¶åœ¨ä¼˜åŒ–冷å¯åŠ¨é—®é¢˜ã€‚ç›®å‰ç»™å¼€å‘者的建议是: -1. 使用clientDBå¯ä»¥å‡å°‘é‡åˆ°å†·å¯åŠ¨é—®é¢˜çš„概率 -2. éžé«˜é¢‘访问的云函数,åˆå¹¶åˆ°é«˜é¢‘云函数ä¸ã€‚也有的开å‘者使用å•è·¯ç”±æ–¹å¼ç¼–写云函数,å³åœ¨ä¸€ä¸ªäº‘函数ä¸é€šè¿‡è·¯ç”±å¤„ç†å®žçŽ°äº†æ•´ä¸ªåº”用的所有åŽå°é€»è¾‘。å‚考[æ’件](https://ext.dcloud.net.cn/search?q=%E8%B7%AF%E7%94%B1&cat1=7&orderBy=UpdatedDate)。 - 但使用这ç§æ–¹å¼éœ€æ³¨æ„平衡,如果业务代ç 太多,æ¯æ¬¡äº‘函数请求产生的内å˜æ¶ˆè€—也会ä¸å°‘。 -3. éžé«˜é¢‘访问的云函数,å¯ä»¥é€šè¿‡å®šæ—¶ä»»åŠ¡æŒç»è¿è¡Œå®ƒï¼ˆæ³¨æ„腾讯云å¯ä»¥ä½¿ç”¨è¿™ä¸ªæ–¹å¼å®Œå…¨é¿å¼€å†·å¯åŠ¨ï¼Œè€Œé˜¿é‡Œäº‘的定时任务最çŸå‘¨æœŸå¤§äºŽèµ„æºå›žæ”¶å‘¨æœŸï¼‰ -4. 阿里云支æŒé…置云函数的å•å®žä¾‹å¤šå¹¶å‘,请å‚考:[å•å®žä¾‹å¤šå¹¶å‘](cf-functions.md?id=concurrency) -5. 腾讯云付费进行实例预留 - -### 实例与请求@instance - -`实例`,指云函数的一个执行环境,å¯ä»¥ç®€å•çš„ç†è§£ä¸ºä¸€ä¸ªnode进程。 - -æ¯æ¬¡å®¢æˆ·ç«¯å‘èµ·`请求`(request)时,serverless的调度ä¸å¿ƒä¼šæŸ¥çœ‹å·²å¯åŠ¨ã€ä¸”空闲的实例,分é…一个实例æ¥æŽ¥æ”¶è¿™ä¸ªè¯·æ±‚。如果没有空闲实例,则新起一个实例。 - -新起一个实例需è¦ä¸€å®šæ—¶é—´ï¼Œä¹Ÿå³ä¸Šæ–‡è¯´çš„冷å¯åŠ¨é—®é¢˜ã€‚详è§[冷å¯åŠ¨](#launchtype) - -一个实例å¯åŠ¨åŽï¼Œä¸€èˆ¬åœ¨1秒内就会完æˆè¯·æ±‚,但serverless调度ä¸å¿ƒä¼šä¿ç•™è¿™ä¸ªå®žä¾‹ä¸€å®šæ—¶é—´ï¼ˆæ—¶é—´è§ä¸Šä¸€èŠ‚)。在实例ä¿ç•™æœŸé—´ï¼Œå®¢æˆ·ç«¯å†æ¬¡è¯·æ±‚云函数,ä¸ä¼šè§¦å‘冷å¯åŠ¨ã€‚ - -也就是说,**在实例ä¿ç•™æœŸé—´ï¼Œ1个实例会接å—多个客户端请求。** - -所以è¦æ³¨æ„`实例`å’Œ`请求`ä¸æ˜¯ä¸€å¯¹ä¸€å…³ç³»ã€‚ - -`请求`(request),指一次连接云函数的网络请求。ä¸åŒè¯·æ±‚有ä¸åŒçš„上下文信æ¯ï¼ˆæ¯”如客户端UA)。 - -所以想è¦èŽ·å–客户端信æ¯ï¼Œä¸€å®šæ³¨æ„ä¸æ˜¯åœ¨å®žä¾‹çš„全局对象上获å–,而是需è¦åœ¨è¯·æ±‚的上下文ä¸èŽ·å–。[详è§]() - -在uniCloud阿里云版,阿里云还æ供了1个实例的多并å‘请求é…置,å³åŒä¸€æ—¶é—´å¤šä¸ªè¯·æ±‚å¯ä»¥å¹¶å‘执行。 -也就是åŒä¸€æ—¶é—´çš„请求å‘到云函数时,没有é…ç½®å•å®žä¾‹å¤šå¹¶å‘会新开一个云函数实例,é…置了å•å®žä¾‹å¤šå¹¶å‘则ä¸ä¼šæ–°å¼€å®žä¾‹ï¼Œåœ¨ä¸€ä¸ªå®žä¾‹ä¸å¢žåŠ 并å‘。 -详è§[å•å®žä¾‹å¤šå¹¶å‘](#concurrency)。 - -一个云函数,å¯ä»¥åŒæ—¶å˜åœ¨å¤šä¸ªå®žä¾‹ã€‚比如cf1云函数,如未é…ç½®å•å®žä¾‹å¤šå¹¶å‘,10个请求åŒæ—¶è¾¾åˆ°äº‘函数,就会开10个实例。 - -ä¸ç®¡å¼€äº†å¤šå°‘实例,云函数的计费是按请求计费的。实例å“应请求åŽåˆ°ä¿ç•™æœŸç»“æŸä¹‹é—´ï¼Œå¦‚æžœä¸å‘生新请求是ä¸ä¼šè®¡è´¹çš„。 - -### äº‘å‡½æ•°çš„æ— çŠ¶æ€å’Œå…¨å±€å˜é‡@state-less - -å› ä¸ºå®žä¾‹å¯èƒ½ç¬¬ä¸€æ¬¡å¯åŠ¨ï¼Œä¹Ÿå¯èƒ½å·²ç»å¯åŠ¨ï¼Œæ‰€ä»¥äº‘函数ä¸çš„js全局å˜é‡å…¶å®žæ˜¯ä¼ªå…¨å±€å˜é‡ã€‚也就是**äº‘å‡½æ•°æ˜¯æ— çŠ¶æ€çš„**。 - -在云函数ä¸ï¼Œå†™åœ¨`module.exports = {}`之å‰ï¼Œäº‘函数写在`exports.main = async (event, context) => {}`之å‰çš„å˜é‡å®šä¹‰ï¼Œæ˜¯ä¼ªå…¨å±€å˜é‡ã€‚ - -它们在实例有效期内的多次请求ä¸ä¼šå¤ç”¨ã€‚ - -以如下代ç 为例,`count`作为全局å˜é‡ï¼Œå½“多次调用该云函数时,å¯èƒ½ä¼šå‡ºçŽ°å˜é‡ç´¯åŠ 的情况。 - -- 云对象示例 -```js -let count = 0; -module.exports = { - methoda() { - return count++ - } -} -``` - -- 云函数示例 - -```javascript -let count = 0; -exports.main = async (event, context) => { - return count++ -} -``` - -上é¢2个示例ä¸ï¼Œå®žä¾‹æœªå¤ç”¨æ—¶ï¼Œä¹Ÿå°±æ˜¯å†·å¯åŠ¨æ—¶ï¼Œcount的值æ¯æ¬¡éƒ½æ˜¯0;若实例被å¤ç”¨ï¼Œåˆ™å¯èƒ½è¿”回1ã€2ã€3ç‰å„ç§æ„外情况。 - -当然,å¯ä»¥ç”¨è¿™ä¸ªæ–¹æ³•æ¥èŽ·çŸ¥ä¸€ä¸ªå®žä¾‹è¢«é‡ç”¨äº†å¤šå°‘次请求。 - -**require由于å˜åœ¨ç¼“å˜ï¼Œä¹Ÿå˜åœ¨åŒæ ·çš„问题。尽é‡ä¸è¦ç›´æŽ¥ä¿®æ”¹require返回的内容。** - -**uniCloud全局对象也是跨请求的,与请求相关的内容ä¸åº”该挂载到uniCloud全局对象上。** - -**æ£ç¡®çš„全局å˜é‡ï¼Œåº”该使用如下方案:** -- uni-config-center:é™æ€å…¨å±€å˜é‡å¯ä»¥ä½¿ç”¨uniæ供的é…ç½®ä¸å¿ƒã€‚[详è§](uni-config-center.md) -- redis:动æ€å…¨å±€å˜é‡ä½¿ç”¨redis。[详è§](redis-introduction.md) - -### 请求的上下文 - -由于上节æ到的,uniCloud全局对象是实例级的ã€è·¨è¯·æ±‚的,1个实例内uniCloudåªä¼šåœ¨å†·å¯åŠ¨æ—¶è¿›è¡Œä¸€æ¬¡åˆå§‹åŒ–。 - -所以与请求相关的上下文,比如客户端信æ¯ï¼Œéœ€è¦é€šè¿‡è¯·æ±‚æ¥èŽ·å–。 - -为了让开å‘者清晰的了解实例和请求的关系,uniCloudæ供了如下方案。 - -1. 通过uniCloud.getRequestList(),å¯ä»¥èŽ·å¾—当å‰å®žä¾‹çš„请求id列表 -æ¯ä¸ªè¯·æ±‚,都有一个requestId,在è¿è¡Œå›žè°ƒé‡Œã€äº‘端日志里都有体现。 -```js -uniCloud.getRequestList() -// 返回值:['3228166e-3c17-4d58-9707-xxxxxxxx'] -``` - - - 如果未é…置阿里云的å•å®žä¾‹å¤šå¹¶å‘,getRequestList()返回的数组里é¢åªæœ‰ä¸€é¡¹ï¼Œå³åªèƒ½æ‹¿åˆ°å½“å‰çš„请求id。 - - 如果é…置了阿里云的å•å®žä¾‹å¤šå¹¶å‘,当并å‘å‘生时,这个列表就会返回多项,当å‰å¹¶å‘çš„æ¯ä¸ªrequestId都在里é¢ã€‚ - -2. uniCloud.getClientInfos(),å¯ä»¥è¿”回当å‰æ‰€æœ‰è¯·æ±‚的客户端信æ¯ã€‚ -该方法返回一个数组,当å‰æ¯ä¸ªå¹¶å‘执行ä¸çš„请求的客户端信æ¯éƒ½åœ¨é‡Œé¢ã€‚ -```json -[ - { - "appId": "__UNI_xxxxx", - "requestId": "3228166e-3c17-4d58-9707-xxxxxxxx" - // ... - } -] -``` - - - 如果未é…置阿里云的å•å®žä¾‹å¤šå¹¶å‘,getRequestList()返回的数组里é¢åªæœ‰ä¸€é¡¹ï¼Œå³åªèƒ½æ‹¿åˆ°å½“å‰çš„请求id。 - - 如果é…置了阿里云的å•å®žä¾‹å¤šå¹¶å‘,当并å‘å‘生时,这个列表就会返回多项,当å‰å¹¶å‘çš„æ¯ä¸ªrequestId都在里é¢ã€‚ - -3. - -如果是uniCloudç§æœ‰äº‘, -如果想获å–与请求相关的信æ¯ï¼Œæ¯”如这次请求的客户端UA,或云函数环境信æ¯ï¼Œæ— 法直接在uniCloud全局对象ä¸èŽ·å–。 - - -云函数入å£å…¥å‚包å«ä¸€ä¸ªevent和一个context,这两个å‚数和请求相关,æ¯æ¬¡æœ‰æ–°è¯·æ±‚到云函数实例时就会有一个新的event对象和一个新的context对象 - -云对象的thiså’Œeventã€context类似,æ¯ä¸ªè¯·æ±‚都对应一个å•ç‹¬çš„this。 - -### å•å®žä¾‹å¤šå¹¶å‘@concurrency - -> ä»…é˜¿é‡Œäº‘æ”¯æŒ - -默认情况下云函数仅支æŒå•å®žä¾‹å•å¹¶å‘,å³åŒä¸€æ—¶é—´ä¸€ä¸ªå®žä¾‹ä»…å¯ä¸ºä¸€ä¸ªè¯·æ±‚æœåŠ¡ï¼ˆä¸åŒè¯·æ±‚åŒä¸€æ—¶é—´è®¿é—®ä¼šè¢«åˆ†æ´¾åˆ°ä¸åŒå®žä¾‹è¿›è¡Œå¤„ç†ï¼‰ã€‚ä¸è¿‡åœ¨uniCloud web控制å°ä¸ï¼Œé˜¿é‡Œäº‘å¯ä»¥é€šè¿‡ä¿®æ”¹äº‘函数å•å®žä¾‹å¹¶å‘度,å¯ä»¥ä¿®æ”¹äº‘函数åŒä¸€æ—¶é—´æœ€å¤šèƒ½å¤„ç†å¤šå°‘请求。 - -å‡è®¾åŒæ—¶æœ‰3个请求需è¦å¤„ç†ï¼š - -当实例并å‘度设置为1时,需è¦åˆ›å»º3个实例æ¥å¤„ç†è¿™3个请求,æ¯ä¸ªå®žä¾‹åˆ†åˆ«å¤„ç†1个请求。而æ¯å¼€å¯ä¸€ä¸ªå®žä¾‹éƒ½ä¼šå¼•å‘云函数冷å¯åŠ¨ï¼› - -当云函数的实例并å‘度设置为10时(å³1个实例å¯ä»¥åŒæ—¶å¤„ç†10个请求),åªéœ€è¦åˆ›å»º1个实例就能处ç†è¿™3ä¸ªè¯·æ±‚ã€‚è¿™æ ·åŽé¢2个并å‘请求ä¸ä¼šæœ‰å› 云函数实例创建带æ¥çš„冷å¯åŠ¨é—®é¢˜ã€‚ - -相关文档:[云函数实例åŠéƒ¨åˆ†å˜é‡è¯´æ˜Ž](#instance) ã€[äº‘å‡½æ•°çš„æ— çŠ¶æ€](#state-less) - -**å¼€å¯æ–¹å¼** - -云函数详情页é¢é…ç½®å•å®žä¾‹å¹¶å‘度å³å¯ï¼Œæ”¯æŒ1-100之间的数值 - -**效果** - -- 有效å‡å°‘并å‘请求时云函数冷å¯åŠ¨æ¬¡æ•° - -**使用注æ„** - -- 虽然阿里云云函数支æŒé…置多并å‘,但在高并å‘下异æ¥è¯·æ±‚排队效果未必好于新开一个实例。尤其是并å‘æ“作数æ®åº“性能ä¸ä½³ã€‚**一般情况下ä¸è¦è®¾ç½®è¿‡å¤§çš„并å‘度,å¯ä»¥è‡ªå·±é’ˆå¯¹ä¸šåŠ¡ä»£ç 测试比较下是å¦å¯ç”¨å¹¶å‘或并å‘æ•°é…æˆå¤šå°‘** -- 云函数内å˜ä½¿ç”¨é‡ä¼šéšç€å¹¶å‘é‡å¢žå¤§è€Œå¢žåŠ ,过大的内å˜å¯èƒ½å¯¼è‡´OOM -- 注æ„云函数是有超时时间的。设置过大的å•å®žä¾‹å¤šå¹¶å‘å¯èƒ½ä¼šå¯¼è‡´å®žä¾‹åº•å±‚网络请求排队从而导致请求超时, -- 如果并å‘çš„ä¸åŒè¯·æ±‚对全局å˜é‡åŒæ—¶è¿›è¡Œè¯»å†™ä¼šæ±¡æŸ“全局å˜é‡ï¼Œå¯èƒ½ä¼šå¯¼è‡´æ„想ä¸åˆ°çš„åŽæžœï¼Œè¯¦è§[全局å˜é‡](#state-less) - -**适用场景** - -|场景 |适用性 |ç†ç”± | -|:-: |:-: |:-: | -|函数ä¸æœ‰è¾ƒå¤šæ—¶é—´åœ¨ç‰å¾…下游æœåŠ¡çš„å“应 |适用 |ç‰å¾…å“应一般ä¸æ¶ˆè€—资æºï¼Œåœ¨ä¸€ä¸ªå®žä¾‹å†…并å‘处ç†å¯ä»¥èŠ‚çœè´¹ç”¨ã€‚ | -|函数ä¸æœ‰å…±äº«çŠ¶æ€ä¸”ä¸èƒ½å¹¶å‘访问 |ä¸é€‚用 |例如全局å˜é‡ï¼Œå¤šè¯·æ±‚并å‘执行修改共享状æ€å¯èƒ½ä¼šå¯¼è‡´é”™è¯¯ã€‚ | -|å•ä¸ªè¯·æ±‚的执行è¦æ¶ˆè€—大é‡CPUåŠå†…å˜èµ„æº |ä¸é€‚用 |多请求并å‘æ‰§è¡Œä¼šé€ æˆèµ„æºäº‰æŠ¢ï¼Œå¯èƒ½ä¼šå¯¼è‡´å†…å˜ä¸è¶³ï¼ˆOOMï¼‰æˆ–è€…å»¶æ—¶å¢žåŠ ã€‚ | - -**关于旧版本uni-id公共模å—的特殊说明** - -旧版本uni-id公共模å—指uni-id-common推出之å‰çš„版本。[详è§](uni-id.md) - -```js -// å¼€å¯å•å®žä¾‹å¤šå¹¶å‘å‰çš„uni-id用法 -const uniID = require('uni-id') -exports.main = async function(event, context) { - const res = uniID.login({ - // ...一些å‚æ•° - }) - return res -} - -// 由于uni-id默认会从一个内置全局å˜é‡ä¸ŠèŽ·å–客户端平å°ä¿¡æ¯ï¼Œä¸åŒè¯·æ±‚会修改æ¤å…¨å±€å˜é‡å¯èƒ½é€ æˆæ··ä¹±ï¼Œå¼€å¯å•å®žä¾‹å¤šå¹¶å‘åŽéœ€è¦å°†uni-id修改为如下写法 -let uniID = require('uni-id') -exports.main = async function(event, context) { - let uniIDIns = uniID.createInstance({ // 创建uni-id实例,其上方法åŒuniID - context: context // ä¼ å…¥context防æ¢ä¸åŒè¯·æ±‚äº’ç›¸å½±å“ - // config: {} // 完整uni-idé…置信æ¯ï¼Œä½¿ç”¨config.json进行é…ç½®æ—¶æ— éœ€ä¼ æ¤å‚æ•° - }) - const res = uniIDIns.login({ - // ...一些å‚æ•° - }) - return res -} -``` - -ä¸åŒäºŽæ—§ç‰ˆuni-id公共模å—,新版uni-id-commonä¸å¯ç›´æŽ¥requireåŽä½¿ç”¨ï¼Œå¿…须使用createInstance方法 - -**进阶** - -å¼€å¯å•å®žä¾‹å¤šå¹¶å‘åŽçš„全局å˜é‡å¤ç”¨å¹¶éžä¸€å®šæ˜¯åçš„ç»“æžœï¼Œå¦‚æžœä½ å¾ˆäº†è§£æ¤è¡Œä¸ºï¼Œä¹Ÿå¯ä»¥å¯¹æ¤è¿›è¡Œæœ‰æ•ˆçš„利用 - -例:[ip-filter](https://ext.dcloud.net.cn/plugin?id=4619)ä¸å°±åˆ©ç”¨äº‘函数全局缓å˜ä¸€äº›ip访问信æ¯æ¥é™åˆ¶å•ip访问频率,å¯ä»¥ä¸‹è½½ç¤ºä¾‹é¡¹ç›®ä½“验一下 - -å—å•å®žä¾‹å¤šå¹¶å‘çš„å½±å“,云函数全局å˜æ”¾ä¸Žæœ¬æ¬¡è¯·æ±‚有关的信æ¯ä¼šé€ æˆæ··ä¹±ã€‚å› æ¤uniCloudæä¾›äº†æ ¹æ®å½“å‰requestId获å–客户端信æ¯å’Œäº‘端信æ¯ã€‚å‚考以下文档 - -- [云函数获å–当å‰requestId](cf-callfunction.md#context) -- [云对象获å–当å‰requestId](cloud-obj.md#get-request-id) -- [获å–当å‰äº‘函数实例æ£åœ¨å¤„ç†çš„请求对应的requestId列表](#get-request-list) -- [获å–当å‰äº‘函数实例æ£åœ¨å¤„ç†çš„请求对应的客户端信æ¯åˆ—表](#get-client-infos) -- [获å–当å‰äº‘函数实例æ£åœ¨å¤„ç†çš„请求对应的云端信æ¯åˆ—表](#get-cloud-infos) - - -### 临时å˜å‚¨ç©ºé—´ - -云函数是è¿è¡Œåœ¨äº‘端的代ç ,è¿è¡ŒçŽ¯å¢ƒç”±äº‘æœåŠ¡å™¨å¼¹æ€§è°ƒé…ï¼Œè¿™æ˜¯å’Œä¼ ç»Ÿ`Node.js`应用很大的区别。 - -æ¢è¨€ä¹‹ï¼Œäº‘函数æ¯æ¬¡æ‰§è¡Œçš„宿主环境(å¯ç®€å•ç†è§£ä¸ºè™šæ‹Ÿæœºæˆ–æœåŠ¡å™¨ç¡¬ä»¶ï¼‰å¯èƒ½ç›¸åŒï¼Œä¹Ÿå¯èƒ½ä¸åŒï¼Œå› æ¤ä¼ 统`Node.js`å¼€å‘ä¸å°†éƒ¨åˆ†ä¿¡æ¯å˜å‚¨æœ¬åœ°ç¡¬ç›˜æˆ–内å˜çš„方案就ä¸å†é€‚åˆã€‚ - -所以,ä¸å»ºè®®ä½¿ç”¨nodeçš„fs文件系统相关的API。建议通过云数æ®åº“ã€äº‘å˜å‚¨ã€redis的方案替代。 - -### 云函数ä¸çš„异æ¥è¡Œä¸º - -书写云函数时应注æ„`async`ã€`await`的使用,`nodejs`有内置模å—`util`å¯ä»¥å°†ç¬¦åˆ`error-first`å½¢å¼`callback`的函数转æ¢ä¸º`promise`å½¢å¼ï¼Œ[详情å‚考](https://nodejs.org/api/util.html#util_util_promisify_original),比如以下示例: - -```js -const { - promisify -} = require('util') - -let testCallback = { - value: 'testCallbackValue', - echo: function(num, callback) { - setTimeout(() => { - // 第一个å‚数为error,第二个为返回值 - callback(null, `${this.value}:${num}`) - }, 2000) - } -} - -exports.main = async function() { - // num=2,ä¸ä¼ å…¥callbackå‚数,callbackä¼šè‡ªåŠ¨ä½œä¸ºå›žè°ƒå‡½æ•°å¤„ç† - let val = await promisify(testCallback.echo).call(testCallback, 2) - console.log(val) - return val -} - -``` - -如果想在云函数内使用回调形å¼å¯ä»¥è®©äº‘函数返回一个promise,如以下示例: - -```js -exports.main = async function() { - return new Promise((resolve, reject) => { - setTimeout(() => { - resolve('some return value') - }, 1000) - }) -} -``` - - -### returnçš„ç–ç•¥@return - -- 阿里云 return 之åŽäº‘函数立å³ç»ˆæ¢ï¼Œé€»è¾‘ä¸ä¼šç»§ç»æ‰§è¡Œï¼ŒåŒ…括 settimeout 或其他异æ¥æ“作都会立å³ç»ˆæ¢ã€‚ -- 腾讯云 node8 return 之åŽä¹Ÿä¸ä¼šç»§ç»æ‰§è¡Œï¼Œä½† node12 å¯ä»¥é…置是å¦ç»§ç»æ‰§è¡Œ -- HBuilderX 本地è¿è¡Œ - * ä¸é€šè¿‡å®¢æˆ·ç«¯å‘起,直接本地è¿è¡Œäº‘函数/云对象,return 之åŽè¿˜å¯ä»¥æ‰§è¡Œ300ms - * 通过客户端连接本地云函数/云对象,return 之åŽå¯ä»¥ç»§ç»æ‰§è¡Œ - -**è…¾è®¯äº‘å› ä¸ºæŒ‰ GBS 对云函数计费,在 node12 时,尤其è¦æ³¨æ„,如果未有效终æ¢äº‘函数,会一直计费** - -### node版本 -云函数è¿è¡Œåœ¨ node 环境ä¸ã€‚å¯ä»¥ä½¿ç”¨ node api `process.version` èŽ·å– node 版本。 - -- uniCloud 阿里云默认是 node8.17.0,也å¯ä»¥åœ¨ package.json ä¸é€‰æ‹© node12 -- uniCloud 腾讯云默认是 node8.9.4,也å¯ä»¥åœ¨ package.json ä¸é€‰æ‹© node12 -- HBuilderX 本地è¿è¡ŒçŽ¯å¢ƒä½¿ç”¨çš„是 HBuilderX 自带的 node 版本,目å‰ä¸º node12。在 package.json 选择 node版本 åªäº‘端生效,且åªåœ¨ç¬¬ä¸€æ¬¡ä¸Šä¼ 云函数时生效。 - -**注æ„** -- 本地开å‘一旦使用了 node12 的专用 apiï¼Œä¸Šä¼ äº‘å‡½æ•°æ—¶å¿…é¡»åœ¨package.json里手动é…置选择 node12 çš„è¿è¡ŒçŽ¯å¢ƒã€‚ - 之所以没有在云端默认统一使用 node12ï¼Œæ˜¯å› ä¸ºè…¾è®¯äº‘ node12 çš„ return ç–略有一些特殊情况,[è§ä¸‹](?id=return)。 -- è¿è¡ŒçŽ¯å¢ƒåœ¨äº‘端云函数创建时设定,ä¸å¯é€šè¿‡æ›´æ–°äº‘函数æ¥ä¿®æ”¹ã€‚ - ä¹Ÿå°±æ˜¯ç¬¬ä¸€æ¬¡ä¸Šä¼ äº‘å‡½æ•°çš„æ—¶å€™ï¼Œpackage.json里é…了什么,就是什么。如果需è¦ä¿®æ”¹nodeçŽ¯å¢ƒï¼Œéœ€å…ˆåˆ é™¤äº‘ç«¯äº‘å‡½æ•°ï¼Œé‡æ–°ä¸Šä¼ 。 - -node版本å¯ä»¥åœ¨äº‘函数的package.json文件的`cloudfunction-config->runtime`å—段进行é…置,详情å‚考:[云函数package.json](uniCloud/cf-functions.md?id=packagejson) - - -### 时区 - -云端的云函数ä¸ä½¿ç”¨çš„时区是 `UTC+0`,而ä¸æ˜¯ `UTC+8`,在云函数ä¸ä½¿ç”¨æ—¶é—´æ—¶éœ€ç‰¹åˆ«æ³¨æ„。 - -云函数在HBuilderX本地è¿è¡Œæ—¶ï¼Œæ—¶åŒºåˆ™æ˜¯ç”µè„‘的时区,很å¯èƒ½æ˜¯ `UTC+8`。建议统一使用时间戳,å¯ä»¥è§„é¿æ—¶åŒºé—®é¢˜ã€‚ - -## 云函数é…ç½® - -云函数除了代ç ,还有é…置。在uniCloud web控制å°å¯ä»¥é…置;在HBuilderX项目ä¸ï¼Œäº‘å‡½æ•°æ ¹ç›®å½•çš„`package.json`也是å˜æ”¾é…置的地方。 - -### 超时时间@timeout - -阿里云éžå®šæ—¶è§¦å‘请求云函数最大åªæ”¯æŒ10秒的超时时间。定时任务触å‘最大支æŒ600秒的超时时间,一般用于跑批。 - -腾讯云最大支æŒ900秒超时时间 - -如果超时时间ä»ç„¶ä¸å¤Ÿç”¨ï¼Œå¯ä»¥å‚考云函数递归调用,连ç»æ‰§è¡Œå¤šä¸ªäº‘函数处ç†ä¸€ä¸ªä»»åŠ¡[详情查看](uniCloud/cf-functions.md?id=recurrence) - -### 固定出å£IP@eip - -#### 腾讯云@tencent-eip - -serverless默认是没有固定的æœåŠ¡å™¨IPçš„ï¼Œå› ä¸ºæœ‰å¾ˆå¤šæœåŠ¡å™¨èµ„æºåœ¨åŽå°ä¾›éšæ—¶è°ƒç”¨ï¼Œæ¯æ¬¡è°ƒç”¨åˆ°å“ªä¸ªæœåŠ¡å™¨ã€å“ªä¸ªip都ä¸å›ºå®šã€‚ - -但一些三方系统,è¦æ±‚é…置固定ip白åå•ï¼Œæ¯”如微信公众å·çš„js sdk,æ¤æ—¶åªèƒ½æ供固定ip地å€ã€‚ - -ç›®å‰è…¾è®¯äº‘的收费版,æ供了云函数的固定出å£ip - -在uniCloud [Web控制å°](https://unicloud.dcloud.net.cn),创建付费的腾讯云æœåŠ¡ç©ºé—´ï¼Œé€‰æ‹©ä¸€ä¸ªäº‘函数,在云函数的详情界é¢å¯ä»¥å¼€å¯å›ºå®šå‡ºå£ip。开å¯åŽç•Œé¢ä¸Šä¼šæ˜¾ç¤ºå¯ç”¨çš„固定ip。拿ç€è¿™ä¸ªip去需è¦å›ºå®šipçš„ç•Œé¢ï¼ˆå¦‚微信公众å·ç®¡ç†ç•Œé¢ï¼‰é…ç½®å³å¯ã€‚ - -**注æ„** - -- å¦‚æžœä½ æ˜¯å…费版å‡é…到付费版,开å¯`固定IP`功能åŽï¼Œä¼šå¯¼è‡´ä»˜è´¹ç‰ˆåˆ°æœŸæ— 法自动é™çº§åˆ°å…费版,请注æ„按时ç»è´¹ - -腾讯云原本的设计是åŒä¸€ä¸ªæœåŠ¡ç©ºé—´å†…所有开å¯å›ºå®šå‡ºå£IP的云函数使用的是åŒä¸€ä¸ªIP。但是对于开通vpcçš„äº‘å‡½æ•°æ— æ³•å’Œæœªå¼€é€švpc的函数共用åŒä¸€ä¸ªå‡ºå£ip。具体使用ä¸æœ‰ä»¥ä¸‹è¡¨çŽ° - -- 开通redis扩展的云函数和未开通redis扩展的云函数会分é…ä¸åŒçš„ip -- 如果一个云函数已ç»å¼€é€šå›ºå®šå‡ºå£ip,å†å…³è”redis扩展库时固定ip会å‘生å˜åŒ– - -建议已开通redisçš„æœåŠ¡ç©ºé—´å…ˆå°†äº‘函数关è”redis扩展å†å¼€é€šå›ºå®šå‡ºå£IP,**2022å¹´7月20æ—¥èµ·æ–°ä¸Šä¼ çš„äº‘å‡½æ•°ä¼šé»˜è®¤å¼€å¯vpc功能,如需旧云函数和新云函数ä¿æŒä¸€è‡´å¯ä»¥æŠŠæ—§äº‘函数关è”redis扩展åŽä¸Šä¼ 一次,注æ„è¿™æ ·æ“作会改å˜æ—§äº‘函数的固定出å£IP** - -#### 阿里云@aliyun-eip - -> 新增于 HBuilderX 3.5.5 - -uniCloud.httpProxyForEip ,其原ç†æ˜¯é€šè¿‡ä»£ç†è¯·æ±‚获得固定出å£IP的能力。IP为轮转ä¸å›ºå®šï¼Œå› æ¤ä¸‰æ–¹æœåŠ¡è¦æ±‚使用白åå•æ—¶å¼€å‘者需è¦å°†ä»£ç†æœåŠ¡å™¨å¯èƒ½çš„IPå‡åŠ 入到白åå•ä¸ï¼Œè§ä¸‹æ–¹ä»£ç†æœåŠ¡å™¨åˆ—表。æ¤å¤–对于代ç†çš„域å有é™åˆ¶ï¼Œå½“å‰ä»…æŒ`weixin.qq.com`泛域å。若开å‘者有其他域å代ç†éœ€æ±‚,å‘é€é‚®ä»¶åˆ°service@dcloud.io申请。 - -代ç†æœåŠ¡å™¨IP列表 - -``` -39.100.3.155 -47.92.39.39 -47.92.67.205 -47.92.25.106 -47.92.68.159 -``` - -如需在获å–微信公众å·access_token场景使用,请将上述ipé…置到`å¾®ä¿¡å…¬ä¼—å¹³å° -> 基本é…ç½® -> IP白åå•`内,相关链接:[微信公众平å°](https://mp.weixin.qq.com/) - -##### å‘é€Get请求@http-proxy-get - -**用法** - -```js -uniCloud.httpProxyForEip.get(url: String, params?: Object) -``` - -**示例** - -```js -await uniCloud.httpProxyForEip.get( - 'https://api.weixin.qq.com/cgi-bin/token', - { - grant_type: 'client_credential', - appid: 'xxxx', - secret: 'xxxx' - } -) -``` - -##### å‘é€POST请求æºå¸¦è¡¨å•æ•°æ®@http-proxy-post-form - -注æ„,æ¤æŽ¥å£ä»¥`application/x-www-form-urlencoded`æ ¼å¼å‘é€æ•°æ®è€Œä¸æ˜¯`multipart/form-data` - -**用法** - -```js -uniCloud.httpProxyForEip.postForm(url: String, data?: Object, headers?: Object) -``` - -**示例** - -```js -uniCloud.httpProxyForEip.postForm( - 'https://www.example.com/search', - { - q: 'nodejs', - cat: '1001' - } -) -``` - -##### å‘é€POST请求æºå¸¦JSONæ•°æ®@http-proxy-post-json - -以`application/json`æ ¼å¼postæ•°æ® - -**用法** - -```js -uniCloud.httpProxyForEip.postJson(url: String, json?: Object, headers?: Object) -``` - -**示例** - -```js -uniCloud.httpProxyForEip.postJson( - 'https://www.example.com/search', - { - q: 'nodejs', - cat: '1001' - } -) -``` - -##### POST通用数æ®@http-proxy-post - -**用法** - -```js -uniCloud.httpProxyForEip.post(url: String, text?: String, headers?: Object) -``` - -**示例** - -```js -uniCloud.httpProxyForEip.post( - 'https://www.example.com/search', - 'abcdefg', - { - "Content-Type": "text/plain" - } -) -``` - -**注æ„** - -- ä¸æ”¯æŒå‘é€multipartæ ¼å¼çš„内容 -- 代ç†è¯·æ±‚超时时间为5秒 -- 上述接å£æ”¯æŒæœ¬åœ°è¿è¡Œ - - -## 云函数package.json@packagejson - -HBuilderX 3.0版本之å‰ï¼Œpackage.jsonåªæ˜¯ä¸€ä¸ªæ ‡å‡†çš„package.json,安装ä¾èµ–或公共模å—æ‰éœ€è¦ã€‚HBuilderX 3.0åŠä»¥ä¸Šç‰ˆæœ¬ï¼Œpackage.json也å¯ä»¥ç”¨æ¥é…置云函数。 - -uniCloud web控制å°æ供了很多云函数的设置,比如内å˜å¤§å°ã€url化ã€å®šæ—¶è§¦å‘ç‰ï¼Œä»ŽHBuilderX 3.0起,在云函数的package.json里也å¯ä»¥ç¼–写这些设置。 - -å¼€å‘è€…åœ¨æœ¬åœ°ç¼–å†™äº‘å‡½æ•°çš„è®¾ç½®ï¼Œä¸Šä¼ äº‘å‡½æ•°ï¼Œè¿™äº›è®¾ç½®ä¼šè‡ªåŠ¨åœ¨äº‘ç«¯ç”Ÿæ•ˆã€‚ï¼ˆæœ¬åœ°ä¸ç”Ÿæ•ˆï¼‰ - -在云端设置了éžé»˜è®¤å‚æ•°åŽï¼ŒHBuilderX下载云函数到本地时,也会自动把设置项放入package.jsonä¸ä¸‹è½½ä¸‹æ¥ã€‚ - -package.jsonæ˜¯ä¸€ä¸ªæ ‡å‡†json文件,ä¸å¯å¸¦æ³¨é‡Šã€‚下é¢æ˜¯ä¸€ä¸ªpackage.json示例。 - -```json -{ - "name": "add-article", - "version": "1.0.0", - "description": "æ–°å¢žæ–‡ç« ", - "main": "index.js", - "dependencies": { - // 云函数的ä¾èµ–,包括公共模å—åŠè‡ªè¡Œå®‰è£…çš„npmä¾èµ– - }, - "extensions": { - // 云函数使用的扩展库 - }, - "cloudfunction-config": { - "memorySize": 256, - "timeout": 5, - "triggers": [{ - "name": "myTrigger", - "type": "timer", - "config": "0 0 2 1 * * *" - }], - "path": "", - "runtime": "Nodejs8" - } -} -``` - -### cloudfunction-config@cloudfunction-config - -å…¶ä¸cloudfunction-configå—段是云函数é…置,支æŒçš„é…置如下 - -```js -{ - "concurrency": 10, // å•ä¸ªäº‘函数实例最大并å‘é‡ï¼Œä¸é…置的情况下默认是1 - "memorySize": 256, // 函数的最大å¯ç”¨å†…å˜ï¼Œå•ä½MB,å¯é€‰å€¼ï¼š 128|256|512|1024|2048,默认值256 - "timeout": 5, // 函数的超时时间,å•ä½ç§’,默认值5。最长为60秒,阿里云在定时触å‘时最长å¯ä»¥æ˜¯600秒 - // triggers å—段是触å‘器数组,目å‰ä»…支æŒä¸€ä¸ªè§¦å‘器,å³æ•°ç»„åªèƒ½å¡«å†™ä¸€ä¸ªï¼Œä¸å¯æ·»åŠ 多个 - "triggers": [{ // 阿里云腾讯云å‡ä¸ºæ¤å½¢å¼ï¼Œè¯·é˜…读下方说明 - // name: 触å‘器的åå—,规则è§https://uniapp.dcloud.net.cn/uniCloud/trigger,nameä¸å¯¹é˜¿é‡Œäº‘生效 - "name": "myTrigger", - // type: 触å‘器类型,目å‰ä»…æ”¯æŒ timer (å³ å®šæ—¶è§¦å‘器),typeä¸å¯¹é˜¿é‡Œäº‘生效 - "type": "timer", - // config: 触å‘器é…置,在定时触å‘器下,config æ ¼å¼ä¸º cron 表达å¼ï¼Œè§„则è§https://uniapp.dcloud.net.cn/uniCloud/trigger。使用阿里云时会自动忽略最åŽä¸€ä½ï¼Œå³ä»£è¡¨å¹´ä»½çš„一ä½åœ¨é˜¿é‡Œäº‘ä¸ç”Ÿæ•ˆ - "config": "0 0 2 1 * * *" - }], - // 云函数Url化path部分,阿里云需è¦ä»¥/http/开头 - "path": "", - "runtime": "", // nodejs版本,å¯é€‰Nodejs8ã€Nodejs12,默认:Nodejs8 - "keepRunningAfterReturn": true // 是å¦åœ¨äº‘函数return之åŽç»§ç»æ‰§è¡Œï¼Œä»…腾讯云nodejs12生效,详情è§ä¸‹æ–¹è¯´æ˜Ž -} -``` - -**使用腾讯云Nodejs12版本时,务必仔细阅读æ¤æ–‡æ¡£ï¼š[keepRunningAfterReturn](#keep-running)** - -#### triggers@triggers - -阿里云定时触å‘çš„cron表达å¼ä¸æ”¯æŒä»£è¡¨å¹´çš„第七ä½ï¼Œä½†æ˜¯åœ¨package.json内é…置时ä»éœ€å°†ç¬¬ä¸ƒä½è®¾ç½®ä¸º*。 - -**在web控制å°é…ç½®trigger请å‚考:[定时触å‘](uniCloud/trigger.md)** - -package.json内统一了腾讯阿里的é…置,两个平å°éƒ½éœ€è¦é…ç½®ä¸ºå¦‚ä¸‹å½¢å¼ - -```js -{ - "name": "myTrigger", - "type": "timer", - "config": "0 0 2 1 * * *" -} -``` - -#### keepRunningAfterReturn@keep-running - -> 新增于HBuilderX 3.5.1 - -阿里云ã€è…¾è®¯äº‘nodejs8在云函数return之åŽå…¶ä½™é€»è¾‘会被冻结ä¸å†æ‰§è¡Œã€‚腾讯云nodejs12表现æ°å¥½ç›¸å,云函数return之åŽè¿˜ä¼šç‰å¾…其余逻辑执行åŽæ‰ä¼šå°†æ¤äº‘函数实例空闲出æ¥ã€‚ - -以下é¢çš„代ç 为例 - -```js -exports.main = async function(event, context) { - setTimeout(()=>{ - console.log('delay 5 seconds') - }, 5000) - return {} -} -``` - -如果æ¤äº‘函数è¿è¡Œåœ¨é˜¿é‡Œäº‘或腾讯云nodejs8,setTimeout里é¢çš„console.logä¸ä¼šåœ¨æœ¬æ¬¡äº‘函数调用执行,但是å¯èƒ½åœ¨äº‘函数实例å†æ¬¡è¢«å¤ç”¨æ—¶ç»§ç»æ‰§è¡Œã€‚ - -如果æ¤äº‘函数è¿è¡Œåœ¨è…¾è®¯äº‘nodejs12,setTimeout里é¢çš„console.log会在本次云函数调用内,åŒæ ·çš„本次云函数**计费时间(与云函数GBsæŒ‡æ ‡ç›¸å…³ï¼‰**也会按照最终执行完æˆçš„时间计算(5000ms+return耗时)。但是å‰ç«¯æ— 需ç‰å¾…5秒å³å¯æ”¶åˆ°å“应。注æ„:如果有未æ–开的长连接(例如:redis连接)会导致云函数一直è¿è¡Œåˆ°é…置的超时时间 - -当在云函数package.json内的cloudfunction-config内é…置了`keepRunningAfterReturn: false`时,å¯ä»¥æ”¹å˜è…¾è®¯äº‘nodejs12的表现,云函数return之åŽå°†ä¸å†ç»§ç»æ‰§è¡Œï¼Œæœªæ–开的长连接也ä¸ä¼šå¢žåŠ 云函数实际è¿è¡Œæ—¶é—´ï¼Œäº‘函数returnåŽé•¿è¿žæŽ¥ä¹Ÿä¸ä¼šè¢«ä¸æ–,简å•æ¥è¯´å…¶è¡¨çŽ°å’Œè…¾è®¯äº‘nodejs8一致。 - -**在云函数ä¸å‘é€ç½‘络请求** - -将上述示例ä¸çš„setTimeoutæ¢æˆç½‘络请求ã€è°ƒç”¨å…¶ä»–云函数或数æ®åº“请求åŒç†ï¼Œå¦‚果在阿里云或腾讯云nodejs8直接return会导致网络请求å¯èƒ½æ— 法å‘é€ï¼ˆå³ä½¿æˆåŠŸå‘é€ä¹Ÿæ˜¯åœ¨ä¸‹ä¸€æ¬¡äº‘函数实例被å¤ç”¨çš„æ—¶å€™ï¼‰ï¼Œè¿™æ˜¯ä¸Žä¼ ç»Ÿå¼€å‘ä¸å¤ªä¸€æ ·çš„地方。 - -```js -exports.main = async function(event, context) { - uniCloud.callFunction({ - name: 'test', - data: {} - }) - return {} // callFunctionåŽä¸ç‰å¾…直接returnæ—¶æ— æ³•è°ƒç”¨åˆ°test云函数 -} -``` - -**腾讯云nodejs12使用redis** - -由于redis需è¦å’ŒæœåŠ¡å™¨å»ºç«‹è¿žæŽ¥ï¼Œæ¤è¿žæŽ¥ä¼šé˜»æ¢äº‘函数结æŸæ‰§è¡Œã€‚如果没有云函数return之åŽè¿˜éœ€è¦ç»§ç»æ‰§è¡Œçš„需求,å¯ä»¥ç®€å•çš„在`cloudfunction-config`内é…ç½®`keepRunningAfterReturn: false`ã€‚è¿™æ ·redis的连接并ä¸ä¼šä¸æ–,下次请求æ¥æ—¶ä¾ç„¶å¯ä»¥ä½¿ç”¨ä¹‹å‰å»ºç«‹çš„连接。 - -如果需è¦return之åŽç»§ç»æ‰§è¡Œï¼Œé‚£ä¹ˆéœ€è¦åœ¨ä½¿ç”¨å®Œæ¯•åŽæ–å¼€redis连接,调用`redis.quit()`方法å³å¯æ–开连接。需è¦æ³¨æ„的是æ–开连接åŽä¹‹å‰å»ºç«‹çš„连接将ä¸å†å¯ç”¨ï¼Œä¸‹ä¸ªè¯·æ±‚到æ¥æ—¶éœ€è¦ä½¿ç”¨`uniCloud.redis()`方法é‡æ–°å»ºç«‹è¿žæŽ¥ã€‚ - -**如未按照上述说明进行æ“作,redis连接将会一直å 用云函数实例,导致云厂商æŒç»è®¡ç®—云函数执行时间,å¯èƒ½ä¼šå¯¼è‡´æ¶ˆè€—大é‡äº‘资æºè€Œäº§ç”Ÿé¢å¤–费用** - -**务必确定自己已ç†è§£æ¤æ–‡æ¡£å†…å®¹ï¼Œå› æœªæŒ‰ç…§æ–‡æ¡£è¯´æ˜Žä½¿ç”¨å¯¼è‡´çš„é¢å¤–计费DCloudä¸æ‰¿æ‹…任何责任** - -### 注æ„事项 - -- æ’件作者在å‘布æ’件时,如果云函数有特殊设置,应该放入package.jsonä¸ï¼Œç„¶åŽå‘布到æ’ä»¶å¸‚åœºã€‚è¿™æ ·å°±ä¸ç”¨å†é€šè¿‡è¯´æ˜Žæ–‡æ¡£ä¸€æ¥ä¸€æ¥å¼•å¯¼ç”¨æˆ·åŽ»é…置云函数定时触å‘器ã€å†…å˜ã€urlåŒ–è·¯å¾„ç‰ -- 在web控制å°ä¿®æ”¹äº‘函数é…ç½®åŽï¼Œé€šè¿‡HBuilderX的下载云函数èœå•ä¼šåœ¨package.jsonå†…æ·»åŠ ä¿®æ”¹åŽçš„云函数é…ç½® -- ä¸Šä¼ äº‘å‡½æ•°æ—¶ï¼Œå¦‚æžœé¡¹ç›®ä¸‹çš„package.json内包å«äº‘函数é…置会åŒæ—¶è¿›è¡Œäº‘函数的é…置更新 -- package.jsonåªæœ‰äº‘端部署æ‰ç”Ÿæ•ˆï¼Œæœ¬åœ°è¿è¡Œä¸ç”Ÿæ•ˆã€‚ -- cloudfunction-configä¸å¯åˆ 除云端é…置。例:云端已é…ç½®triggers(定时触å‘å™¨ï¼‰ï¼Œåˆ é™¤cloudfunction-config内的triggerä¸ä¼šåˆ 掉云端的定时触å‘器 -- runtimeå‚数(nodejs版本)仅å¯åœ¨åˆ›å»ºäº‘函数时生效,ä¸å¯ä¿®æ”¹ - - -### 云函数的数é‡ã€ä½“积ã€å†·å¯åŠ¨çš„平衡 - -鉴于: -- æ¯ä¸ªæœåŠ¡ç©ºé—´çš„云函数数é‡æ˜¯æœ‰é™çš„,阿里云是48个,腾讯云是9~149个,[详è§](price.md) -- æ¯ä¸ªäº‘函数的体积é™åˆ¶æ˜¯10M(å«node_modules) -- 云函数有冷å¯åŠ¨é—®é¢˜ - -基于以上情况,对开å‘模å¼æœ‰å¦‚下建议: - -1. 一般ä¸å»ºè®®ä½¿ç”¨ä½“积较大ã€ä¾èµ–较深的node_modules。多使用DCloud官方或æ’件市场æ供的库。 -2. 优先使用clientDB,ä¸å 用云函数数é‡ï¼Œä¹Ÿä¸ç”¨ç¼–写æœåŠ¡å™¨ä»£ç 。 -3. 对云对象或云函数åšé€‚当的åˆå¹¶å’Œæ‹†è§£ã€‚ - - 低频且对用户体验影å“较大的æ“作ä¸å»ºè®®ç‹¬ç«‹ä½¿ç”¨äº‘函数,åˆå¹¶åˆ°é«˜é¢‘云函数ä¸ã€‚ - - 控制好å•ä¸ªäº‘函数体积,有的开å‘者喜欢使用[å•è·¯ç”±äº‘函数](https://ext.dcloud.net.cn/search?q=%E8%B7%AF%E7%94%B1&orderBy=WeekDownload&cat1=7),整个æœåŠ¡ç©ºé—´å°±ä¸€ä¸ªäº‘å‡½æ•°ã€‚è¿™ä¹Ÿå¾—æ ¹æ®å®žé™…情况,如果云函数体积超过6M也还是建议分拆。 - - 用户体系方é¢ï¼Œå®˜æ–¹å·²ç»æä¾›uni-id-co云对象,å†æé…clientDB,常规业务就够了。有特殊需求å¯ä»¥å†é€‚度补若干云对象。ä¸å¤ªä¼šå‘生云函数数é‡ä¸è¶³çš„情况。 -4. å¿…è¦æ—¶å¯ä»¥ä½¿ç”¨å¤šä¸ªæœåŠ¡ç©ºé—´ï¼Œè·¨æœåŠ¡ç©ºé—´ä½¿ç”¨ - -## cloudfunctions_init(已废弃) - -`HBuilderX 2.9`版本,`uniCloud`æ供了`cloudfunctions_init.json`æ¥æ–¹ä¾¿å¼€å‘者快速进行云函数的åˆå§‹åŒ–æ“作。 - -**注æ„:HBuilderX 3.0.0版本起ä¸å†ä½¿ç”¨cloudfunctions_init.jsonæ¥åˆå§‹åŒ–云函数。改为使用在云函数目录下通过package.json进行é…置,具体è§ä¸Šä¸ªç« 节** - -详细调整如下: - -ä¸å†ä½¿ç”¨cloudfunctions_init.json,内容被分散到æ¯ä¸ªäº‘函数的package.jsonçš„`cloudfunction-config`å—段下 - -package.jsonæ˜¯ä¸€ä¸ªæ ‡å‡†json文件,ä¸å¯å¸¦æ³¨é‡Šã€‚下é¢æ˜¯ä¸€ä¸ªpackage.json示例 - -```json -{ - "name": "add-article", - "version": "1.0.0", - "description": "æ–°å¢žæ–‡ç« ", - "main": "index.js", - "dependencies": { - - }, - "cloudfunction-config": { - "memorySize": 256, - "timeout": 5, - "triggers": [{ - "name": "myTrigger", - "type": "timer", - "config": "0 0 2 1 * * *" - }], - "path": "" - } -} -``` - -cloudfunction-config说明如下 - -```js -{ - "memorySize": 256, // 函数的最大å¯ç”¨å†…å˜ï¼Œå•ä½MB,å¯é€‰å€¼ï¼š 128|256|512|1024|2048,默认值256 - "timeout": 5, // 函数的超时时间,å•ä½ç§’,默认值5。最长为60秒,阿里云在定时触å‘时最长å¯ä»¥æ˜¯600秒 - // triggers å—段是触å‘器数组,目å‰ä»…支æŒä¸€ä¸ªè§¦å‘器,å³æ•°ç»„åªèƒ½å¡«å†™ä¸€ä¸ªï¼Œä¸å¯æ·»åŠ 多个 - "triggers": [{ - // name: 触å‘器的åå—,规则è§https://uniapp.dcloud.net.cn/uniCloud/trigger,nameä¸å¯¹é˜¿é‡Œäº‘生效 - "name": "myTrigger", - // type: 触å‘器类型,目å‰ä»…æ”¯æŒ timer (å³ å®šæ—¶è§¦å‘器),typeä¸å¯¹é˜¿é‡Œäº‘生效 - "type": "timer", - // config: 触å‘器é…置,在定时触å‘器下,config æ ¼å¼ä¸º cron 表达å¼ï¼Œè§„则è§https://uniapp.dcloud.net.cn/uniCloud/trigger。使用阿里云时会自动忽略最åŽä¸€ä½ï¼Œå³ä»£è¡¨å¹´ä»½çš„一ä½åœ¨é˜¿é‡Œäº‘ä¸ç”Ÿæ•ˆ - "config": "0 0 2 1 * * *" - }], - // 云函数Url化path部分,阿里云需è¦ä»¥/http/开头 - "path": "" -} -``` - -**HBuilderX 3.0.0之å‰ç‰ˆæœ¬ï¼Œè¯·ç»§ç»é˜…读下é¢æ–‡æ¡£** - -**使用方å¼** -- 在`cloudfucntions`目录å³é”®å³å¯åˆ›å»º`cloudfunctions_init.json`, -- 编写好json内容,在`cloudfunctions_init.json`上å³é”®åˆå§‹åŒ–云函数é…置。 - -**cloudfunctions_init.jsonå½¢å¼å¦‚下** - -```json -{ - "fun-name": { // 云函数å称 - "memorySize": 256, // 函数的最大å¯ç”¨å†…å˜ï¼Œå•ä½MB,å¯é€‰å€¼ï¼š 128|256|512|1024|2048,默认值256 - "timeout": 5, // 函数的超时时间,å•ä½ç§’,默认值5。 - // triggers å—段是触å‘器数组,目å‰ä»…支æŒä¸€ä¸ªè§¦å‘器,å³æ•°ç»„åªèƒ½å¡«å†™ä¸€ä¸ªï¼Œä¸å¯æ·»åŠ 多个 - "triggers": [{ - // name: 触å‘器的åå—,规则è§https://uniapp.dcloud.net.cn/uniCloud/trigger,nameä¸å¯¹é˜¿é‡Œäº‘生效 - "name": "myTrigger", - // type: 触å‘器类型,目å‰ä»…æ”¯æŒ timer (å³ å®šæ—¶è§¦å‘器),typeä¸å¯¹é˜¿é‡Œäº‘生效 - "type": "timer", - // config: 触å‘器é…置,在定时触å‘器下,config æ ¼å¼ä¸º cron 表达å¼ï¼Œè§„则è§https://uniapp.dcloud.net.cn/uniCloud/trigger。使用阿里云时会自动忽略最åŽä¸€ä½ï¼Œå³ä»£è¡¨å¹´ä»½çš„一ä½åœ¨é˜¿é‡Œäº‘ä¸ç”Ÿæ•ˆ - "config": "0 0 2 1 * * *" - }], - // 云函数Url化path部分,阿里云需è¦ä»¥/http/开头 - "path": "" - } -} - -``` +## 简介@intro + +云函数是è¿è¡Œåœ¨äº‘端的 `JavaScript` 代ç ,是基于 `Node.js` 的扩展。 + +在常规的 `Node API` 基础上,uniCloud的云函数环境内置了`uniCloud`对象,这个对象内置了网络ã€æ•°æ®åº“ç‰å„ç§API。开å‘者未å¦ä¹ 过 `Node.js` 也没有关系,åªéœ€è¦çœ‹uniCloud的文档,掌æ¡è¿™ä¸ª`uniCloud`对象的APIå³å¯ã€‚ + +æ¯ä¸ªäº‘函数是一个js包,在云函数被调用时,由 serverless 调度系统分é…硬件资æºå¯åŠ¨ä¸€ä¸ª node 环境æ¥è¿è¡Œè¿™ä¸ªäº‘函数。 + +在HBuilderXä¸å¯ä»¥æ–°å»ºäº‘函数(HBuilderX 3.4 åŒæ—¶å¯ä»¥æ–°å»ºäº‘对象)。 + + +æ¯ä¸ªäº‘函数是一个目录,其ä¸æ™®é€šäº‘函数有`index.js`å…¥å£æ–‡ä»¶ï¼Œäº‘对象的入å£æ–‡ä»¶åˆ™æ˜¯`index.obj.js`。 + +一个最简å•çš„云函数åªéœ€è¦è¿™ä¸ªå…¥å£js文件,在里é¢ç¼–写代ç å³å¯ã€‚当然也å¯ä»¥åœ¨è¿™ä¸ªjsä¸require该云函数目录下的其他jsã€json文件。 + +云函数的é…置文件和 npm规范 相åŒï¼Œåœ¨äº‘函数目录下å¯æ–°å»ºä¸€ä¸ª package.json æ¥å˜æ”¾é…置。uniCloud云函数扩展了 package.jsonï¼Œå¢žåŠ äº†ä¸€äº›ç‰¹æœ‰çš„é…置项。[详è§](/uniCloud/cf-functions?id=packagejson) + +云函数å¯åŠ¨åŽå®žä¾‹ä¼šä¿ç•™ä¸€æ®µæ—¶é—´ï¼ˆå¦‚15分钟),超过ä¿ç•™æœŸåŽè‹¥è¯¥äº‘函数一直没有被å†è°ƒç”¨ï¼Œé‚£è¿™ä¸ªå®žä¾‹ä¼šè¢«é‡Šæ”¾ã€‚所以云函数有冷å¯åŠ¨çš„概念。ä¸è¿‡ç”±äºŽjs实例的å¯åŠ¨è¦æ¯”phpå’Œjava更快,所以js更适åˆserverlessæ–¹å¼ã€‚ + +**注æ„事项** +- 云函数内使用commonjs规范,ä¸å¯ä½¿ç”¨importã€export,å‚考:[commonjs模å—](http://nodejs.cn/api/modules.html#modules_modules_commonjs_modules) +- ä¸åŒé¡¹ç›®ä½¿ç”¨åŒä¸€ä¸ªæœåŠ¡ç©ºé—´æ—¶ï¼Œä¸å¯ä½¿ç”¨åŒå云函数。åŒå云函数会相互覆盖。 +- 在HBuilderX创建云函数时,如果新云函数与æœåŠ¡å™¨ä¸Šå·²å˜åœ¨åŒå云函数,会用新函数覆盖。所以应先选择从æœåŠ¡ç©ºé—´ä¸‹è½½äº‘函数。 +- å•ä¸ªäº‘函数大å°é™åˆ¶ä¸º10M(包å«`node_modules`),过大的云函数影å“è¿è¡Œæ€§èƒ½ï¼Œä¹Ÿä¼šå¢žåŠ 计费的gbs。åŒæ—¶è…¾è®¯äº‘支æŒåœ¨äº‘端安装`node_modules`,æ¤æ—¶ä¸å 用云函数体积。 +- uniCloud的阿里云版,暂ä¸å¯ä½¿ç”¨ç›¸å¯¹è·¯å¾„读å–文件(比如`fs.readFileSync('./info.txt')`),å¯ä»¥ä½¿ç”¨ç»å¯¹è·¯å¾„`fs.readFileSync(path.resolve(__dirname,'./info.txt'))` + +## 云函数的分类 + +云函数有若干å概念,包括 普通云函数ã€äº‘对象ã€å…¬å…±æ¨¡å—ã€clientDBçš„action云函数ã€uniCloud扩展库。 + +- äº‘å‡½æ•°ï¼šé€šè¿‡ä¼ ç»Ÿjson接å£æ–¹å¼å’Œå®¢æˆ·ç«¯é€šä¿¡ï¼Œå®¢æˆ·ç«¯ä½¿ç”¨`uniCloud.callfunction("")`调用云函数 +- 云对象:是通过å‰ç«¯å¯¼å…¥å¯¹è±¡æ¥æ“作的,客户端使用`uniCloud.importObject("")`导入云对象。详è§[云对象](/uniCloud/cloud-obj) +- 公共模å—:用于ä¸åŒçš„云函数/云对象,抽å–和共享相åŒä»£ç ,详è§[公共模å—文档](/uniCloud/cf-functions?id=公共模å—) +- action云函数:为了弥补clientDB客户端直接æ“作数æ®åº“çš„å±€é™è€Œè®¾è®¡çš„,详è§[clientDB action文档](/uniCloud/clientdb?id=action) +- uniCloud扩展库:为了è£å‰ªå’ŒæŽ§åˆ¶äº‘函数体积而设计的,一些ä¸å¤ªå¸¸ç”¨çš„功能比如Redis,独立为å¯é€‰æ‰©å±•åº“,é¿å…增大æ¯ä¸ªäº‘函数的体积,详è§[uniCloud扩展库](/uniCloud/cf-functions?id=扩展库) + +HBuilderXä¸uniCloud项目的云函数å‡åœ¨é¡¹ç›®çš„`uniCloud/cloudfunctions`目录下,目录结构如下: + +<pre v-pre="" data-lang=""> + <code class="lang-" style="padding:0"> +|——— cloudfunctions 云函数目录 +| │───common 云函数公用模å—目录 <a target="_blank" href="https://uniapp.dcloud.net.cn/uniCloud/cf-common">详情</a> +| | └──hello-common äº‘å‡½æ•°å…¬ç”¨æ¨¡å— +| | │──index.js 公用模å—代ç +| | └──package.json 公用模å—package.json +| │───uni-clientDB-actions +| │ └──new_action.js clientDB action代ç <a target="_blank" href="https://uniapp.dcloud.net.cn/uniCloud/clientdb?id=action">详情</a> +| │───function-name 云函数目录 +| │ │──index.js 云函数代ç +| │ └──package.json 包å«äº‘函数的é…置信æ¯ï¼Œå¦‚url化ã€å®šæ—¶è®¾ç½®ã€å¯ç”¨å†…å˜ç‰å†…容 <a target="_blank" href="https://uniapp.dcloud.net.cn/uniCloud/cf-functions?id=packagejson">详情</a> +| └───object-name 云对象目录 +| │──index.obj.js 云对象代ç +| └──package.json 包å«äº‘对象的é…置信æ¯ï¼Œå¯ç”¨å†…å˜ç‰å†…容 <a target="_blank" href="https://uniapp.dcloud.net.cn/uniCloud/cf-functions?id=packagejson">详情</a> + </code> +</pre> + +## 客户端和云函数的通信@clientcallfunction + +uni-appå®¢æˆ·ç«¯å’Œä¼ ç»ŸæœåŠ¡å™¨é€šä¿¡æ—¶ï¼Œä½¿ç”¨`uni.request`çš„ajax请求方å¼ã€‚uniCloud下ä¸å†ä½¿ç”¨å®ƒï¼Œæœ‰æ›´å¥½çš„云端一体的通信方å¼ã€‚ + +uniCloud体系里,客户端和æœåŠ¡ç«¯çš„云函数通信,有4ç§æ–¹å¼ï¼š + +| |ä¼ ç»Ÿçš„restfulæ–¹å¼|callfunctionæ–¹å¼|云对象方å¼|clientDBæ–¹å¼| +|:-:|:-:|:-:|:-:|:-:| +|简述 |通过é…ç½®[云函数URL化](/uniCloud/http)ï¼ŒæŠŠäº‘å‡½æ•°è½¬ä¸ºä¼ ç»Ÿçš„http链接 |云函数默认并ä¸è‡ªå¸¦http链接|把callfunction的函数å¼è°ƒç”¨ï¼Œå‡çº§ä¸ºæ¨¡å—化的对象调用|客户端直接æ“作云数æ®åº“| +|å‰ç«¯è°ƒç”¨æ–¹å¼|ä¼ ç»Ÿajax|uni-app客户端通过`uniCloud.callFunction(functionname)`æ¥è°ƒç”¨äº‘函数|uni-app客户端通过`uniCloud.importObject(objectname)`导入一个云对象,直接使用这个对象的方法 |uni-app客户端通过`<uniCloud-db>`组件或`uniCloud.database()` APIæ¥è®¿é—®uniCloudæ•°æ®åº“。也支æŒæé…actionäº‘å‡½æ•°è¿½åŠ æœåŠ¡å™¨é€»è¾‘ | +|适用场景 |http链接需è¦è‡ªå·±æ³¨å†ŒåŸŸå。如果å‰ç«¯æ˜¯uni-app,则ä¸æŽ¨è使用URL化。如果是éžuni-app的系统需è¦è®¿é—®äº‘函数,åªèƒ½ä½¿ç”¨URL化 |相比云函数URL,callfunctionæ›´åŠ å®‰å…¨ã€æ›´serverless,ä¸æš´éœ²åŸŸåå’Œip,ä¸æ€•æ”»å‡»ï¼Œä¹Ÿæ— 需注册域å|uni-app 3.4起支æŒã€‚相比callfunctionæ–¹å¼ã€‚代ç æ›´åŠ ç²¾ç®€ã€é€»è¾‘æ›´åŠ æ¸…æ™°ã€å¼€å‘æ›´åŠ é«˜æ•ˆ |如果uni-appå‰ç«¯å‘èµ·çš„æœåŠ¡å™¨è¯·æ±‚目的主è¦æ˜¯æŸ¥è¯¢æˆ–æ“作数æ®åº“,则推è使用clientDBæ–¹å¼| + +云函数是uniCloud的基础,本质上 clientDB å’Œ 云对象 都是建立在云函数上针对特定场景的优化。 +- clientDB针对的场景是数æ®åº“æ“作,它优化了å¯ä»¥ä¸å†™æˆ–少写æœåŠ¡å™¨ä»£ç +- 云对象针对的场景是éžæ•°æ®åº“æ“作或ä¸å®œå‰ç«¯æš´éœ²çš„æ•°æ®åº“æ“作时,和uni-app客户端的通信方å¼ã€‚它优化了代ç 结构,更精简ã€ç®€å• + + +### clientDBæ–¹å¼ + +**直观体验代ç 示例** + +clientDB分APIæ–¹å¼å’Œç»„件方å¼ï¼Œæ¤å¤„使用APIæ–¹å¼æ¥æ¼”示 +```js +// 客户端js直接æ“作云数æ®åº“,查询list表的数æ®ã€‚æ— éœ€æœåŠ¡å™¨ä»£ç +const db = uniCloud.database() // 获å–云数æ®åº“的引用 +db.collection('list').get() + .then((res)=>{ + // res 为数æ®åº“查询结果 + }).catch((err)=>{ + console.log(err); + }) +``` + +由于篇幅较长,å¦ä¹ clientDB需å¦è§æ–‡æ¡£[clientDB](clientdb.md) + +- clientDB适用的情况: + +如果客户端使用uni-appå¼€å‘,且å‘uniCloudæœåŠ¡ç©ºé—´çš„请求主è¦æ˜¯ä¸ºäº†æ“作云数æ®åº“ï¼ˆæ— è®ºå¢žåˆ æ”¹æŸ¥ï¼‰ï¼Œé‚£ä¹ˆæŽ¨è使用clientDBæ–¹å¼ï¼Œç”±uni-app客户端直接æ“作云数æ®åº“。 + +如果æ“作数æ®åº“çš„åŒæ—¶ï¼Œè¿˜éœ€è¦åŒæ—¶æ‰§è¡Œä¸€äº›äº‘函数,å¯ä»¥ä½¿ç”¨clientDBçš„action云函数。 + +- clientDBä¸é€‚用的情况: + +1. 请求ä¸æ“作云数æ®åº“,比如å‘外部web系统å‘请求ã€æ“作redisã€åˆ 除云文件ç‰ï¼› +2. æ“作的云数æ®åº“请求ä¸å¸Œæœ›æš´éœ²åœ¨å‰ç«¯ï¼› +3. æ•°æ®åº“表和å—段数é‡å¤šè€ŒæŽ¥å£æ•°é‡å°‘。给æ¯ä¸ªæ•°æ®é…ç½®æƒé™çš„工作é‡è¶…过了控制少数接å£æƒé™çš„工作é‡ï¼› +4. æƒé™ä½“系较å¤æ‚,除了用户和管ç†å‘˜å¤–还有较多其他æƒé™æ¡ä»¶æˆ–动æ€æƒé™ã€‚æ¤æ—¶åœ¨schemaå’Œactionä¸ç¼–写代ç çš„å¤æ‚度超过了写接å£ã€‚ + +### äº‘å¯¹è±¡æ–¹å¼ + +云对象和clientDB最大的区别,是云对象把数æ®åº“æ“作(以åŠå…¶ä»–逻辑)å°è£…在云对象的方法里é¢ã€‚ + +å®ƒæ— æ³•åƒclientDBé‚£æ ·æ— éœ€å¼€å‘æœåŠ¡å™¨ä»£ç ,它ä»éœ€åœ¨å®¢æˆ·ç«¯å’Œäº‘端分别写代ç 。但它的应用场景ä¸å—é™åˆ¶ã€‚上文ä¸ä¸é€‚用clientDB的情况,都å¯ä»¥ä½¿ç”¨äº‘对象解决。 + +**直观体验代ç 示例** + +云端云对象代ç ,云对象å称:testco,有一个sum方法 + +```js +module.exports = { + sum(a, b) { + // æ¤å¤„çœç•¥aå’Œbçš„æœ‰æ•ˆæ€§æ ¡éªŒ + return a + b + } +} +``` + +然åŽåœ¨å®¢æˆ·ç«¯çš„jsä¸ï¼Œimport这个testco对象,调用它的sum方法 + +```js +const testco = uniCloud.importObject('testco') //第一æ¥å¯¼å…¥äº‘对象 +async function sum () { //注æ„方法或生命周期需使用async异æ¥æ–¹å¼ + try { + const res = await testco.sum(1,2) //导入云对象åŽå°±å¯ä»¥ç›´æŽ¥è°ƒç”¨è¯¥å¯¹è±¡çš„方法了,注æ„使用异æ¥await + console.log(res) // 结果是3 + } catch (e) { + console.log(e) + } +} +``` + +由于篇幅较长,å¦ä¹ 云对象需å¦è§æ–‡æ¡£[云对象](cloud-obj.md) + +clientDB和云对象å¯ä»¥æ··åˆä½¿ç”¨ï¼š +1. 比如官方æ供了[uni-id-pages](uni-id-pages.md),是基于云对象的登录注册系统,开å‘者å¯ä»¥å¯¼å‡ºè¿™ä¸ªæ’件处ç†è´¦æˆ·ä½“系,然åŽå‰©ä½™çš„业务如果ä¸ç®—å¤æ‚,就å¯ä»¥ä½¿ç”¨clientDBæžå®šã€‚ +2. 一个业务的用户端和admin端也å¯ä»¥æ˜¯ä¸åŒçš„æŠ€æœ¯æ ˆã€‚æ¯”å¦‚ä¸šåŠ¡ç«¯æœ‰å¤æ‚的动æ€æƒé™ï¼Œè€Œç®¡ç†ç«¯åªæœ‰ä¸€ä¸ªadmin管ç†å‘˜ä½¿ç”¨ï¼Œé‚£ä¹ˆadmin端使用[schema2code](schema2code.md)会éžå¸¸é«˜æ•ˆï¼Œè€Œè¿™äº›æŠ€æœ¯éƒ½åŸºäºŽclientDB。 + +### 普通云函数callFunctionæ–¹å¼ + +- 普通云函数适用的情况: + +在HBuilderX 3.5.2之å‰ï¼Œéœ€è¦URL化和定时è¿è¡Œæ—¶ï¼Œåªèƒ½ä½¿ç”¨æ™®é€šäº‘函数;在HBuilderX 3.5.2+,云对象也支æŒäº†URL化和定时è¿è¡Œã€‚ + +官方ä¸æŽ¨èå¼€å‘者使用云函数,有相关需求推è使用云对象替代云函数。 + +ç›®å‰å®˜æ–¹è¿˜æœªæ供基于云对象的router模å¼çš„框架,有相关需求å¯ä»¥ä½¿ç”¨ä¸‰æ–¹æ¡†æž¶ã€‚ + +**直观体验代ç 示例** + +```js +// 客户端å‘起调用云函数hellocfï¼Œå¹¶ä¼ å…¥dataæ•°æ® +uniCloud.callFunction({ + name: 'hellocf', + data: {a:1,b:2} +}).then((res) => { + console.log(res.result) // 结果是 {sum: 3} +}).catch((err) => { + console.error(err) +}) +``` + +```js +// 云函数hellocf的代ç ï¼ŒæŽ¥æ”¶åˆ°å®¢æˆ·ç«¯ä¼ é€’çš„data,并对其ä¸aå’Œbç›¸åŠ è¿”å›žç»™å®¢æˆ·ç«¯ +'use strict'; +exports.main = async (event, context) => { + //eventä¸ºå®¢æˆ·ç«¯ä¸Šä¼ çš„å‚æ•° + console.log('event : ', event) + //æ¤å¤„çœç•¥event.aå’Œevent.bçš„æœ‰æ•ˆæ€§æ ¡éªŒ + //返回数æ®ç»™å®¢æˆ·ç«¯ + return {sum : event.a + event.b} +}; + +``` + +由于篇幅较长,需å¦è§æ–‡æ¡£[云函数callfunctionæ–¹å¼](/uniCloud/cf-callfunction) + +### 云函数URLåŒ–æ–¹å¼ + +å¯ä»¥è®©äº‘函数/云对象生æˆä¸€ä¸ªHTTP URLã€‚è¿™æ ·éžuni-app应用,å¯ä»¥é€šè¿‡ajax请求和云函数/云对象通信。 + +在 uniCloud Web控制å°è¿›è¡ŒURL化é…置。 + +由于篇幅较长,需å¦è§æ–‡æ¡£[云函数URL化](http.md)。 + + +### uniCloudå“应体规范@resformat + +`uniCloudå“应体规范`(uniCloud response format),是DCloud制定的ã€æœåŠ¡å™¨ç»™å®¢æˆ·ç«¯è¿”回jsonæ•°æ®çš„一ç§å»ºè®®æ ¼å¼ã€‚ + +云对象ã€clientDBã€uni-id公共模å—å‡æ”¯æŒæ¤è§„范。 + +**ç”±æ¥** + +uniCloudæœåŠ¡å™¨ç»™å®¢æˆ·ç«¯è¿”回的数æ®æ ¼å¼ä¸€èˆ¬æ˜¯json,但jsonçš„æ ¼å¼å…·ä½“是什么没有约定。比如返回错误ç ,是å«`code`还是å«`errCode`?错误内容是`message`还是`errMsg`?内容的国际化如何处ç†ï¼Ÿ + +å¦‚æžœæ²¡æœ‰ä¸€å¥—ç»Ÿä¸€çš„æ ¼å¼ï¼Œåœ¨å®¢æˆ·ç«¯å°†æ— æ³•ç¼–å†™æœ‰æ•ˆçš„ç½‘ç»œæ‹¦æˆªå™¨ï¼Œæ— æ³•ç»Ÿä¸€å¤„ç†é”™è¯¯ã€‚ + +å¦å¤–,如果ä¸åŒçš„æ’件,云端返回的数æ®æ ¼å¼åƒå·®ä¸‡åˆ«ï¼Œé‚£ä½¿ç”¨è€…æ•´åˆè¿™äº›æ’件也会éžå¸¸éº»çƒ¦ã€‚å›½é™…åŒ–æ›´æ— æ³•è½åœ°ã€‚ + +为æ¤DCloud推出了`uniCloudå“应体规范`。 + +为了与uni-appå‰ç«¯çš„APIé”™è¯¯å›žè°ƒé£Žæ ¼ç»Ÿä¸€ï¼ŒuniCloudå“应体规范定义的云端返回信æ¯ï¼ˆå°¤å…¶æ˜¯æŠ¥é”™æ—¶ï¼‰åº”包å«`errCode`å’Œ`errMsg`。 + +除æ¤ä¹‹å¤–å“应体规范还包å«`newToken`å—段,用于token的自动ç»æœŸï¼ˆäº‘对象接收å«æœ‰newTokençš„å“应åŽä¼šè‡ªåŠ¨æ›´æ–°storage内å˜å‚¨çš„`uni_id_token`åŠ`uni_id_token_expired`,æ¤è¡Œä¸ºæ–°å¢žäºŽ`HBuilderX 3.4.13`)。开å‘è€…ä¸€èˆ¬æ— éœ€å…³å¿ƒæ¤æ•°æ®ï¼Œuni-app客户端和云端uni-id之间会自动管ç†tokenåŠç»æœŸã€‚ + +`uniCloudå“应体`示例如下: + +```json +// 失败返回值 +{ + "errCode": 'uni-id-account-banned', + "errMsg": 'è´¦å·è¢«ç¦ç”¨' +} +``` + +```json +// æˆåŠŸè¿”回值 +{ + "errCode": 0, + "errMsg": '登录æˆåŠŸ', + "uid": 'xxx', // å…¶ä»–ä¿¡æ¯ + "newToken": { // 用于下å‘æ–°token给客户端 + "token": 'xxx', + "tokenExpired": 'xxx' + } +} +``` + +HBuilderX内使用代ç å—`returnu`å¯ä»¥å¿«é€Ÿè¾“入以下代ç (`HBuilderX 3.4.0`åŠä»¥ä¸Šç‰ˆæœ¬ï¼‰: + +```js +return { + errCode: 0, + errMsg: '' +} +``` + +- errCode + +errCode在æˆåŠŸæ—¶åº”返回数å—`0`,失败时应返回一个以æ’件id开头的“å—符串â€ï¼Œæ¯ä¸ªå•è¯ä»¥è¿žå—符(`-`)分割。åšå‡ºè¿™æ ·çš„规定是为了防æ¢ä¸åŒæ’件之间出现é‡å¤é”™è¯¯ç + +以`'uni-id-account-banned'`错误ç 为例,`uni-id`为æ’件id,`account-banned`为错误缩写。 + +如果业务开å‘的代ç 并ä¸å‘布æ’件市场,那么为了é¿å…下载了一个市场的æ’件产生冲çªï¼ŒæŽ¨è使用ä¸åŒ…å«â€œ-â€çš„å—符串æ¥åšerrCode(æ’件市场的所有æ’件ID必须包å«â€œ-â€ï¼‰ã€‚ + +åŽç»uniCloud会æä¾›è‡ªåŠ¨æ ¹æ®errCode对errMsg进行国际化处ç†çš„功能,开å‘者仅需ä¿è¯äº‘函数返回值满足`uniCloudå“应体规范`å³å¯ã€‚ + +- errMsg + +errMsg用于å˜æ”¾å…·ä½“错误信æ¯ï¼ŒåŒ…括展示给开å‘者ã€ç»ˆç«¯ç”¨æˆ·çš„é”™è¯¯ä¿¡æ¯ + +## uniCloud API列表 + +äº‘å‡½æ•°æ”¯æŒ js å’Œ nodejs çš„æ ‡å‡†API,如`console.log()`ã€`setTimeout()`,å¦è§[nodejs官网](https://nodejs.org/en/docs/)。nodejs版本,详è§[云函数è¿è¡ŒçŽ¯å¢ƒ](?id=runtime) + +é™¤äº†æ ‡å‡†API外,云函数环境ä¸å†…置了`uniCloud`对象,扩展了一批新API,实际开å‘ä¸æ›´å¸¸ç”¨çš„是uniCloud的扩展API。è§ä¸‹ï¼š + +|API |æè¿° | +|-- |-- | +|uniCloud.database() |云数æ®åº“对象 [详情](uniCloud/cf-database.md) | +|uniCloud.databaseJQL() |云函数ä¸ä½¿ç”¨JQLè¯æ³•æ“作数æ®åº“ [详è§](uniCloud/jql-cloud.md)ï¼Œéœ€æ·»åŠ æ‰©å±•åº“ | +|uniCloud.redis() |使用redis [详è§](uniCloud/redis.md)ï¼Œéœ€æ·»åŠ æ‰©å±•åº“ +|uniCloud.uploadFile() |äº‘å‡½æ•°ä¸Šä¼ æ–‡ä»¶åˆ°äº‘å˜å‚¨ [详情](uniCloud/storage?id=clouduploadfile) | +|uniCloud.downloadFile() |云函数下载云å˜å‚¨çš„文件到云函数è¿è¡ŒçŽ¯å¢ƒ [详情](uniCloud/storage?id=clouddownloadfile) | +|uniCloud.deleteFile() |äº‘å‡½æ•°åˆ é™¤äº‘å˜å‚¨çš„文件 [详情](uniCloud/storage?id=clouddeletefile) | +|uniCloud.getTempFileURL() |获å–云å˜å‚¨æ–‡ä»¶çš„临时路径 [详情](uniCloud/storage?id=cloudgettempfileurl) | +|uniCloud.customAuth() |使用云厂商自定义登录,仅腾讯云支æŒ[详情](uniCloud/authentication.md?id=cloud-custom-auth) | +|uniCloud.callFunction() |云函数/云对象ä¸è°ƒç”¨å¦ä¸€ä¸ªäº‘函数 [è§ä¸‹](#callbyfunction) | +|uniCloud.importObject() |云函数/云对象ä¸è°ƒç”¨å¦ä¸€ä¸ªäº‘对象 [详情](cloud-obj.md?id=call-by-cloud) | +|uniCloud.httpclient |云函数ä¸é€šè¿‡http访问其他系统 [è§ä¸‹](#httpclient) | +|uniCloud.httpProxyForEip |使用云厂商代ç†è®¿é—®httpæœåŠ¡ï¼ˆé˜¿é‡Œäº‘的解决微信需è¦å›ºå®šIPçš„æ–¹æ¡ˆï¼‰ï¼Œä»…é˜¿é‡Œäº‘äº‘ç«¯çŽ¯å¢ƒæ”¯æŒ [详è§](#aliyun-eip),新增于`HBuilderX 3.5.5`| +|uniCloud.sendSms() |å‘é€çŸä¿¡ï¼Œéœ€æ·»åŠ 扩展库 [详è§](uniCloud/send-sms.md) | +|uniCloud.getPhoneNumber() |获å–一键登录手机å·ï¼Œéœ€æ·»åŠ 扩展库 [详è§](uniCloud/univerify.md?id=cloud) | +|uniCloud.init() |获å–指定æœåŠ¡ç©ºé—´çš„uniCloud实例 [详è§](uniCloud/concepts/space.md?id=multi-space) | +|uniCloud.logger |云函数ä¸æ‰“å°æ—¥å¿—到[uniCloud web控制å°](https://unicloud.dcloud.net.cn/)的日志系统(éžHBuilderX控制å°ï¼‰[详情](rundebug.md?id=uniCloudlogger) | +|uniCloud.getRequestList |获å–当å‰äº‘函数实例内æ£åœ¨å¤„ç†çš„请求Id列表 [详è§](#get-request-list),新增于`HBuilderX 3.5.5`| +|uniCloud.getClientInfos |获å–当å‰äº‘函数实例内æ£åœ¨å¤„ç†çš„请求对应的客户端信æ¯åˆ—表 [详è§](#get-client-infos),新增于`HBuilderX 3.5.5`| +|uniCloud.getCloudInfos |获å–当å‰äº‘函数实例内æ£åœ¨å¤„ç†çš„请求对应的云端信æ¯åˆ—表 [详è§](#get-cloud-infos),新增于`HBuilderX 3.5.5`| + +## 错误对象@uni-cloud-error + +云函数调用uniCloud接å£æ—¶ï¼ˆåŒ…括请求云函数ã€äº‘对象ã€äº‘å˜å‚¨ç‰ï¼‰å¯èƒ½å˜åœ¨æŠ›å‡ºé”™è¯¯çš„场景,æ¤æ—¶ä¼šæŠ›å‡ºuniCloudæ ‡å‡†çš„é”™è¯¯å¯¹è±¡ï¼ˆä»¥ä¸‹è®°ä¸ºuniCloudError),uniCloudError包å«ä»¥ä¸‹å±žæ€§ + +|属性 |类型 |必备 |说明 | +|-- |-- |-- |-- | +|errCode |string |是 |错误ç | +|errMsg |string |是 |é”™è¯¯ä¿¡æ¯ | +|requestId |string |å¦ |请求Id,用于排查错误 | +|detail |object |å¦ |仅云对象主动返回错误对应的å“应体规范时会有æ¤å±žæ€§ | + +å¦å¤–uniCloudError对象上还有code属性和message属性,两者å‡ä¸æŽ¨è使用。 + +## 访问数æ®åº“ + +云函数ä¸æ”¯æŒè®¿é—®æœ¬æœåŠ¡ç©ºé—´ä¸‹çš„ã€æˆ–ç»æŽˆæƒçš„其他æœåŠ¡ç©ºé—´ä¸‹çš„,数æ®åº“。 + +- 使用 MongoDB è¯æ³•æ“作数æ®åº“,å¦è§[文档](uniCloud/cf-database.md) +- 使用 JQL è¯æ³•æ“作数æ®åº“,å¦è§[文档](uniCloud/jql-cloud.md) + +## 访问其他HTTPæœåŠ¡@httpclient + +云函数ä¸å¦‚需è¦è¯·æ±‚其他httpæœåŠ¡ï¼Œåˆ™ä½¿ç”¨`uniCloud.httpclient`ã€‚æ— éœ€é¢å¤–ä¾èµ–,就å¯ä»¥è¯·æ±‚任何 HTTP å’Œ HTTPS å议的 Web æœåŠ¡ã€‚`uniCloud.httpclient`返回的是一个[urllib实例](https://github.com/node-modules/urllib)。 + +**uniCloud.httpclient.request(URL,requestOptions)** + +**requestOptionså‚数说明** + +|å‚æ•°å |类型 |是å¦å¿…å¡« |默认值 |说明 | +|---- |---- |---- |---- |---- | +|method |String | - |GET |HTTP 请求方法, 默认为:GET. å¯é€‰å€¼ï¼š GET, POST, DELETE, PUT | +|data |Object | - |- |å‘é€çš„æ•°æ® | +|dataAsQueryString |Boolean | - |true |是å¦å¼ºåˆ¶è½¬æ¢data为queryString | +|content |String | Buffer | - |- |手动设置请求的payload,设置åŽä¼šå¿½ç•¥data | +|stream |ReadStream |- |- |å‘é€è¯·æ±‚æ£æ–‡çš„å¯è¯»æ•°æ®æµ | +|writeStream |WriteStream |- |- |接å—å“应数æ®çš„å¯å†™æ•°æ®æµ | +|consumeWriteStream |Boolean |- |true |是å¦ç‰å¾… writeStream 完全写完æ‰ç®—å“应全部接收完毕 | +|files |Array<ReadStream|Buffer|String> | Object | ReadStream | Buffer | String| - |- |ä¸Šä¼ çš„æ–‡ä»¶ï¼Œè®¾ç½®åŽå°†ä¼šä½¿ç”¨ multipart/form-data æ ¼å¼ã€‚如果未设置method,将会自动将method设置为POST | +|contentType |String | - |- |ä¸Šä¼ æ•°æ®çš„æ ¼å¼ï¼Œè®¾ä¸º`json`会自动在`header`内设置`Content-Type: application/json` | +|nestedQuerystring |Boolean | - |- |转æ¢data为queryString时默认ä¸æ”¯æŒåµŒå¥—Object,æ¤é€‰é¡¹è®¾ç½®ä¸ºtrue则支æŒè½¬æ¢åµŒå¥—Object | +|dataType |String | - |- |返回的数æ®æ ¼å¼ï¼Œå¯é€‰å€¼ä¸º 'json'(返回数æ®è½¬ä¸ºJSON),'text'(返回数æ®è½¬ä¸ºå—符串), ''(返回数æ®ä¸åšå¤„ç†ï¼Œé»˜è®¤å€¼ï¼‰ | +|fixJSONCtlChars |Boolean |- |false |在JSON.parse之å‰å¤„ç†å“应结果ä¸çš„控制å—符(Control Character) | +|headers |Object | - |- |请求头 | +|timeout |Number | Array | - |5000 |超时时间设置。设置为数组时第一项为请求超时,第二项为返回超时。设置为数å—时相当于åŒæ—¶è®¾ç½®è¯·æ±‚超时和返回超时,å³`timeout:3000`效果ç‰äºŽ`timeouut:[3000,3000]` | +|auth |String |- |- |简å•ç™»å½•æŽˆæƒï¼ˆBasic Authentication)å‚数,必须按照 `user:password` æ ¼å¼è®¾ç½® | +|digestAuth |String |- |- |摘è¦ç™»å½•æŽˆæƒï¼ˆDigest Authentication)å‚数,必须按照 `user:password` æ ¼å¼è®¾ç½® | +|agent |[http.Agent](https://nodejs.org/api/http.html#http_class_http_agent) |- |- |http代ç†ï¼Œå¦‚ä¸ä½¿ç”¨å¯è®¾ä¸ºfalse | +|httpsAgent |[https.Agent](https://nodejs.org/api/https.html#https_class_https_agent) |- |- |https代ç†ï¼Œå¦‚ä¸ä½¿ç”¨å¯è®¾ä¸ºfalse | +|ca |String|Buffer|Array |- |- |è¯ä¹¦å†…容 | +|rejectUnauthorized |Boolean |- |true |是å¦åœ¨è¯ä¹¦ä¸å—信任时返回错误 | +|pfx |String|Buffer |- |- |包å«äº†ç§é’¥, è¯ä¹¦å’ŒCA certs, 一般是 PFX 或者 PKCS12 æ ¼å¼ | +|key |String|Buffer |- |- |PEFæ ¼å¼çš„æœåŠ¡å™¨çš„ç§é’¥ | +|cert |String|Buffer |- |- |PEMæ ¼å¼çš„æœåŠ¡å™¨è¯ä¹¦å¯†é’¥ | +|passphrase |String |- |- |ç§é’¥æˆ–pfx密ç çš„å—符串 | +|ciphers |String |- |- |使用或排除的cipher | +|secureProtocol |String |- |- |SSL 使用的方法,例如,`SSLv3_method` 强制 SSL 版本为3。 | +|followRedirect |Boolean |- |false |收到3xxå“应时是å¦è‡ªåŠ¨é‡å®šå‘ | +|maxRedirects |Number |- |10 |最高é‡å®šå‘次数 | +|formatRedirectUrl |Function |- |- |æ‰‹åŠ¨æ ¼å¼åŒ–url | +|beforeRequest |Function |- |- |请求å‘é€å‰çš„é’©å | +|streaming |Boolean |- |false |是å¦ç›´æŽ¥è¿”回å“应æµï¼Œå¼€å¯ streaming 之åŽï¼ŒHttpClient 会在拿到å“应对象 res 之åŽé©¬ä¸Šè¿”回, æ¤æ—¶ result.headers å’Œ result.status å·²ç»å¯ä»¥è¯»å–到,åªæ˜¯æ²¡æœ‰è¯»å– data æ•°æ®è€Œå·²ã€‚| +|gzip |Boolean |- |false |是å¦æ”¯æŒ gzip å“åº”æ ¼å¼ã€‚å¼€å¯ gzip 之åŽï¼ŒHttpClient 将自动设置 Accept-Encoding: gzip 请求头, 并且会自动解压带 Content-Encoding: gzip å“应头的数æ®ã€‚ | +|timing |Boolean |- |false |是å¦å¼€å¯è¯·æ±‚å„é˜¶æ®µçš„æ—¶é—´æµ‹é‡ | +|enableProxy |Boolean |- |false |是å¦å¯ç”¨ä»£ç† | +|proxy |String |- |null | 代ç†åœ°å€ | +|lookup |Function |- |- |自定义DNS查询函数 | +|checkAddress |Function |- |- |æ ¡éªŒè¯·æ±‚åœ°å€ | +|trace |Boolean |- |false |是å¦å¯ç”¨æ•èŽ·å †æ ˆ | + +**注æ„** + +默认情况下request接å£ä¸ä¼šå¤„ç†è¿”回的数æ®ï¼Œå³ä¸ä¼ `dataType`å‚数时会返回buffer类型的数æ®ï¼Œå¦‚需自动解æžjsonæ ¼å¼çš„返回结果,需è¦å°†`dataType`设置为`"json"` + +**示例代ç ** + +```js +const res = await uniCloud.httpclient.request(apiUrl, { + method: 'POST', + data: { + test: 'testValue' + }, + contentType: 'json', // 指定以application/jsonå‘é€dataå†…çš„æ•°æ® + dataType: 'json' // 指定返回值为jsonæ ¼å¼ï¼Œè‡ªåŠ¨è¿›è¡Œparse + }) +console.log(res) +``` + +返回数æ®ç»“构如下 + +```js +{ + "data": {"name": "DCloud"}, // å“应内容 + "status": 200, // 状æ€ç + "headers": { // å“应头,仅作示例,ä¸åŒæœåŠ¡å™¨è¿”回的有差异 + "date": "Tue, 29 Dec 2020 08:10:30 GMT", + "content-type": "application/json", + "content-length": "276", + "connection": "keep-alive", + "server": "gunicorn/19.9.0", + "access-control-allow-origin": "*", + "access-control-allow-credentials": "true" + } +} + +``` + +### å‘é€formdataç±»åž‹æ•°æ® + +实际业务ä¸å¸¸æœ‰ä½¿ç”¨äº‘函数å‘é€formdata类型数æ®çš„需求,比如微信å°ç¨‹åºæ供的一些æœåŠ¡ç«¯æŽ¥å£ï¼ˆå›¾ç‰‡å†…容安全检测ã€è¯†åˆ«å›¾ç‰‡äºŒç»´ç ç‰ï¼‰ï¼Œå¯ä»¥å‚考以下示例进行å‘é€ + +```js +'use strict'; +const fs = require('fs') +const path = require('path') +const FormData = require('form-data'); // æ¤form-data需è¦ä½¿ç”¨npm安装,地å€ï¼šhttps://www.npmjs.com/package/form-data +exports.main = async (event, context) => { + const form = new FormData() + form.append('media', fs.readFileSync(path.resolve(__dirname, './test.jpg')), { // 为方便演示æ¤å¤„直接使用云函数目录下的test.jpg文件 + filename: 'test.jpg', + contentType: 'image/jpeg' + }); + form.append('otherParam', 'otherParam content'); + const res = await uniCloud.httpclient.request('https://httpbin.org/post', { + method: 'POST', + content: form.getBuffer(), // 请求内容 + headers: form.getHeaders(), // 请求头 + dataType: 'json' // æ¤å¤„指定为json表示将æ¤è¯·æ±‚的返回值解æžä¸ºjson + }) + return res +}; + +``` + +## 请求和环境API + +由于å˜åœ¨[å•å®žä¾‹å¤šå¹¶å‘](#concurrency)的情况,实例级的uniCloud对象,和æ¯ä¸ªè¯·æ±‚request是一对多的关系。 + +è¿™ä¹Ÿé€ æˆäº†ä¸Žè¯·æ±‚相关的上下文,比如客户端信æ¯ï¼Œéœ€è¦é€šè¿‡è¯·æ±‚æ¥èŽ·å–。 + +为了更好的管ç†è¯·æ±‚和请求相关的上下文,uniCloudæ供了下é¢ä¸€æ‰¹API。 + +### 获å–请求id列表@get-request-list + +**示例** + +```js +uniCloud.getRequestList() +// 返回值:['3228166e-3c17-4d58-9707-xxxxxxxx'] +``` + +如没有é…ç½®[å•å®žä¾‹å¤šå¹¶å‘](#concurrency),数组里åªä¼šè¿”回一项内容。é…ç½®åŽå¯èƒ½ä¼šå¤šé¡¹ï¼Œæ£åœ¨å¹¶å‘的所有请求的requestId都会返回。 + +当返回多项时,在uniCloudå¯¹è±¡ä¸Šæ— æ³•æ˜Žç¡®å½“å‰è¯·æ±‚是数组ä¸çš„哪一个。所以æ供了其他方法æ¥èŽ·å–当å‰è¯·æ±‚: +- 云对象通过`this.getUniCloudRequestId()`。[详情](cloud-obj.md#get-request-id) +- 云函数通过函数自带å‚æ•°context。[详情](cf-callfunction.md#context) + +### 获å–客户端信æ¯åˆ—表#get-client-infos + +åŒç†ï¼Œè€ƒè™‘到å•å®žä¾‹å¤šå¹¶å‘,`uniCloud.getClientInfos()`获å–客户端信æ¯ä¹Ÿæ˜¯ä¸€ä¸ªæ•°ç»„。 + +```js +const clientInfos = uniCloud.getClientInfos() +``` + +返回值 +```js +clientInfos = [{ + appId: '__UNI_xxxxx', + requestId: '3228166e-3c17-4d58-9707-xxxxxxxx' + // ... +}] +``` + +如未开å¯å•å®žä¾‹å¤šå¹¶å‘,那么数组åªæœ‰1项。å•å®žä¾‹å¤šå¹¶å‘场景下返回æ£åœ¨å¹¶å‘的所有请求的客户端信æ¯åˆ—表。 + +**返回值** + +getClientInfos返回的信æ¯ï¼Œæ˜¯åœ¨å®¢æˆ·ç«¯çš„[uni.getSystemInfo](/api/system/info.md#getsysteminfo)çš„åŸºç¡€ä¹‹ä¸Šï¼Œå¢žåŠ äº†ä¸€äº›é¢å¤–çš„ä¿¡æ¯ã€‚ + +除了`getSystemInfo`返回å—段外,还包å«ä»¥ä¸‹ä¿¡æ¯ + +|属性å |类型 |说明 | +|-- |-- |-- | +|requestId|string |请求Id,å¯ä»¥ä½¿ç”¨æ¤å—段ç›é€‰å‡ºå½“å‰è¯·æ±‚çš„å®¢æˆ·ç«¯ä¿¡æ¯ | +|clientIP |string |客户端ip | +|userAgent|string |客户端ua,注æ„éžæœ¬åœ°è¿è¡ŒçŽ¯å¢ƒä¸‹å®¢æˆ·ç«¯getSystemInfoSync也会获å–uaå‚æ•°å¹¶ä¸Šä¼ ç»™äº‘å¯¹è±¡ï¼Œä½†æ˜¯äº‘å¯¹è±¡ä¼šä»Žhttp请求头里é¢èŽ·å–ua而ä¸æ˜¯clientInfo里é¢çš„ua| +|source |string |调用æ¥æºï¼Œè¿”回值è§ä¸‹ã€‚ | +|scene |string |场景值。客户端[uni.getLaunchOptionsSync](/api/plugins/getLaunchOptionsSync.md#getlaunchoptionssync)返回的sceneå‚数, | + +云函数调用æ¥æºsource,它的值域为: + +|å–值 |说明 | +|-- |-- | +|client |uni-app客户端导入云对象调用 | +|function |由其他云函数或云对象调用 | +|http |云对象URL化åŽé€šè¿‡http访问调用| +|timing |定时任务调用云对象 | + +**注æ„事项** + +- 客户端上报的信æ¯åœ¨ç†è®ºä¸Šå˜åœ¨è¢«ç¯¡æ”¹å¯èƒ½ï¼Œå®žé™…业务ä¸åº”验è¯å‰ç«¯ä¼ æ¥çš„æ•°æ®çš„åˆæ³•æ€§ +- 除了clientIP外,其他客户端信æ¯åªæœ‰ä½¿ç”¨uni-app客户端以callFunction或者importObjectæ–¹å¼è®¿é—®äº‘函数或云对象时æ‰æœ‰ +- 云对象与云函数内获å–客户端platformç¨æœ‰ä¸åŒï¼Œäº‘函数未拉é½vue2ã€vue3版本appå¹³å°çš„platform值,vue2为`app-plus`,vue3为`app`ã€‚äº‘å¯¹è±¡æ— è®ºå®¢æˆ·ç«¯æ˜¯vue2还是vue3,在appå¹³å°èŽ·å–çš„platformå‡ä¸º`app`。这一点在使用uni-id时需è¦ç‰¹åˆ«æ³¨æ„,详情è§ï¼š[uni-id文档 preferedAppPlatform](uniCloud/uni-id.md?id=prefered-app-platform) + +除了`uniCloud.getClientInfos()`API,在云函数context和云对象thisä¸ï¼Œä¹Ÿå¯ä»¥ç›´æŽ¥èŽ·å–当å‰å®¢æˆ·ç«¯ä¿¡æ¯ã€‚ +- 云对象通过`this.getClientInfo()`。[详情](cloud-obj.md#get-client-info) +- 云函数通过函数自带å‚æ•°context。[详情](cf-callfunction.md#context) + +### 获å–云端信æ¯@get-cloud-infos + +åŒä¸Šï¼Œä¸ºäº†å…¼å®¹å¹¶å‘场景,获å–云端信æ¯`uniCloud.getCloudInfos()`返回的也是数组。 + +**示例** + +```js +const cloudInfos = uniCloud.getCloudInfos() +cloudInfos = [{ + provider: 'aliyun', + spaceId: 'xxxxx', + functionName: 'xxx', + functionType: 'xxxx', + requestId: '3228166e-3c17-4d58-9707-xxxxxxxx' +}] +``` + +**返回值** + +|å‚æ•°å |类型 |必备 |说明 | +|-- |-- |-- |-- | +|provider |string |是 |æœåŠ¡ç©ºé—´ä¾›åº”商,阿里云为:`aliyun`,腾讯云为:`tencent`| +|spaceId |string |是 |æœåŠ¡ç©ºé—´Id | +|functionName |string |是 |云函数å称 | +|functionType |string |是 |云对象为`cloudobject`ã€äº‘函数为`cloudfunction` | +|requestId |string |是 |请求Id,å¯ä»¥ä½¿ç”¨æ¤å—段ç›é€‰å‡ºå½“å‰è¯·æ±‚çš„äº‘ç«¯ä¿¡æ¯ | + +除了`uniCloud.getCloudInfos()`API,在云函数context和云对象thisä¸ï¼Œä¹Ÿå¯ä»¥ç›´æŽ¥èŽ·å–当å‰è¯·æ±‚的云端信æ¯ã€‚ +- 云对象通过`this.getCloudInfo()`。[详情](cloud-obj.md#get-cloud-info) +- 云函数通过函数自带å‚æ•°context。[详情](cf-callfunction.md#context) + + +上述3个APIï¼Œéƒ½å› ä¸ºå•å®žä¾‹å¤šå¹¶å‘而被设计æˆæ•°ç»„æ–¹å¼ã€‚实际上,大多数开å‘者并ä¸ä½¿ç”¨å•å®žä¾‹å¤šå¹¶å‘。 + +在ä¸è€ƒè™‘å•å®žä¾‹å¤šå¹¶å‘时,也å¯ä»¥ç›´æŽ¥ä½¿ç”¨uniCloudçš„getRequestListã€getClientInfosã€getCloudInfos方法ä¸ç¬¬ä¸€ä¸ªæ•°ç»„项。 + +或者在云对象的this和云函数的context里获å–相关上下文信æ¯ä¹Ÿå¯ä»¥ã€‚ + + +## 扩展库@extension + +uniCloudçš„apiä¸ï¼Œæœ‰äº›api对应的实现,其代ç 体积较大,且这些功能并ä¸æ˜¯æ¯ä¸€ä¸ªäº‘函数都会使用。为了方便开å‘者控制云函数的体积,设计了`uniCloud扩展库`的概念。 + +å¼€å‘者å¯ä»¥å¯¹äº‘函数目录点å³é”®ï¼Œç®¡ç†å…¬å…±æ¨¡å—和扩展库ä¾èµ–,在其ä¸é€‰æ‹©è¦åŠ 载的扩展库。这个å¯è§†åŒ–ç•Œé¢å¯¹åº”çš„æ•°æ®åœ¨äº‘函数目录下的 package.json 内的`extensions`å—段下。 + +注æ„:未引用扩展库的,使用uniCloud相应api时会报错。 + + +**ç›®å‰æ”¯æŒçš„扩展库如下** + +- JQL扩展库[uni-cloud-jql]:用于在云函数内使用JQLè¯æ³•æ“作数æ®åº“,详è§ï¼š[JQL扩展库](uniCloud/jql-cloud.md) +- redis扩展库[uni-cloud-redis]:云函数内使用redis,详è§ï¼š[redis扩展库](uniCloud/redis.md) +- å‘é€çŸä¿¡æ‰©å±•[uni-cloud-sms]:云函数ä¸å‘é€çŸä¿¡ï¼Œè¯¦è§ï¼š[sms扩展](uniCloud/send-sms?id=extension) +- 一键登录API扩展[uni-cloud-verify]:手机App调用è¿è¥å•†ä¸€é”®ç™»é™†æœåŠ¡æ—¶ï¼Œäº‘函数ä¸èŽ·å–到真实手机å·ï¼Œ 详è§ï¼š[一键登陆扩展库](uniCloud/univerify?id=extension) +- 统一推é€æœåŠ¡æ‰©å±•åº“[uni-cloud-push]:云函数内使用uni-push,详è§ï¼š[uniCloud/uni-cloud-push/api] + +以下是一个开å¯äº†redis扩展库的云函数package.json示例,注æ„æ¤æ–‡ä»¶ä¸æ”¯æŒæ³¨é‡Šï¼Œä¸‹æ–¹ç¤ºä¾‹ä¸çš„注释仅为演示 + +```js +{ + "name": "add-article", + "version": "1.0.0", + "description": "æ–°å¢žæ–‡ç« ", + "main": "index.js", + "extensions": { + "uni-cloud-redis": {} // é…置为空对象å³å¯ï¼ŒåŽç»å¦‚有扩展å‚数会在æ¤å¤„é…ç½® + } +} +``` + +## 公共模å—@common + +云函数支æŒå…¬å…±æ¨¡å—。多个云函数的共享部分,å¯ä»¥æŠ½ç¦»ä¸ºå…¬å…±æ¨¡å—,然åŽè¢«å¤šä¸ªäº‘函数引用。由于篇幅较长,[详è§](uniCloud/cf-common) + +## 使用npm + +云函数的è¿è¡ŒçŽ¯å¢ƒæ˜¯ `Node.js`ï¼Œå› æ¤æˆ‘们å¯ä»¥ä½¿ç”¨ `npm` 安装第三方ä¾èµ–。 + +注æ„:阿里云目å‰ä»…支æŒå…¨é‡ä¸Šä¼ 云函数(整个 node_modulesæ–‡ä»¶å¤¹å…¨éƒ¨ä¸Šä¼ ï¼‰ï¼Œå› æ¤æ醒开å‘者精简ä¾èµ–,å¦åˆ™å¯èƒ½ä¼šæ¯æ¬¡ä¸Šä¼ 时间很慢,影å“å¼€å‘体验。并且太大的npm库影å“云函数的è¿è¡Œæ€§èƒ½ã€‚ + +è…¾è®¯äº‘ä¼šåœ¨ä¸Šä¼ äº‘å‡½æ•°åŽè‡ªåŠ¨å®‰è£…需è¦çš„npmä¾èµ–。 + +Tips: +- ç›®å‰æ¯ä¸ªäº‘å‡½æ•°ä¸Šä¼ åŒ…å¤§å°é™åˆ¶ä¸º10M。如果npmåŒ…å¾ˆå¤§ï¼Œé˜¿é‡Œäº‘çš„æ•´ä½“ä¸Šä¼ æœºåˆ¶ä¼šæ— æ³•æ»¡è¶³éœ€æ±‚ã€‚æ¤æ—¶åªèƒ½é€‰æ‹©è…¾è®¯äº‘,交给腾讯云自动安装ä¾èµ–。 + + +## 云函数/云对象ä¸è°ƒç”¨äº‘函数@callbyfunction + +### 调用三方云函数或云对象 + +用法åŒå®¢æˆ·ç«¯è°ƒç”¨äº‘函数,ä»ç„¶æ˜¯`uniCloud.callfunction`,但ä¸æ”¯æŒcallbackå½¢å¼ã€‚ + +**请求å‚æ•°** + +|å—段 |类型 |å¿…å¡« |说明 | +|--- |--- |--- |--- | +|name |String |是 |云函数å称。 | +|data |Object |å¦ |云函数å‚数。 | + +**å“应å‚æ•°** + +|å—段 |类型 |必备 |说明 | +|--- |--- |--- |--- | +|errCode |String |å¦ |状æ€ç ,æ“作æˆåŠŸåˆ™ä¸è¿”回。 | +|errMsg |String |å¦ |错误æ述。 | +|result |Object |å¦ |云函数执行结果。 | +|requestId|String |å¦ |请求åºåˆ—å·ï¼Œç”¨äºŽé”™è¯¯æŽ’查。 | + +**示例代ç ** + +```javascript +let callFunctionResult = await uniCloud.callFunction({ + name: "test", + data: { a: 1 } +}) +``` + +**注æ„** + +由于调用方ä¸æ˜¯uni-app客户端,云函数的contextã€äº‘对象的this.getClientInfoç‰APIæ— æ³•èŽ·å–客户端信æ¯ï¼ŒåŒ…括 uni-id-token。 + +å¯ä»¥åœ¨äº‘å‡½æ•°äº’è°ƒæ—¶æ‰‹åŠ¨ä¼ é€’ token ï¼Œæˆ–è€…æ ¡éªŒè°ƒç”¨æ¥æºï¼ˆsource)为云函数(function)时ä¸éªŒè¯ç”¨æˆ· token。 + +云函数/云对象互相调用时调用方会通过公网访问被调用方,访问速度ä¸å¦‚直接将逻辑放在调用方执行。使用å‰è¯·ç¡®ä¿ä½ 确实需è¦æ¤åŠŸèƒ½ã€‚ + +`HBuilderX 3.4.0`版本之å‰**云函数å³é”®æœ¬åœ°è¿è¡Œæ—¶**,里é¢çš„代ç å†æ¬¡callFunction会调用云端的云函数而ä¸æ˜¯æœ¬åœ°äº‘函数,æ¤bugåŽç»ç‰ˆæœ¬å·²ä¿®å¤ã€‚ + +### 云函数递归调用自身@recurrence + +除了调用三方云函数,事实上云函数还å¯ä»¥é€’归调用自己。 + +当一个云函数实例的资æºä¸èƒ½æ»¡è¶³éœ€æ±‚,或超时时间ä¸å¤Ÿç”¨æ—¶ã€‚比如è¦ç»™10万个用户å‘é€çŸä¿¡ï¼Œè€ŒçŸä¿¡å‘é€æŽ¥å£ä¸€æ¬¡è°ƒç”¨æœ€å¤šæ”¯æŒ50个手机å·ç ï¼Œè¿™æ ·æœ€å°‘éœ€è¦è°ƒç”¨2000次接å£æ‰èƒ½å®Œæˆï¼›è€Œä¸€ä¸ªäº‘函数实例完æˆä¸äº†2000次接å£çš„调用。这ç§åœºæ™¯å°±å¯ä»¥ä½¿ç”¨äº‘函数递归调用,分解任务实现。 + +示例代ç 如下: + +```js +// 当å‰äº‘函数å称 send-sms-cf +'use strict'; +const db = uniCloud.database(); +const dbCmd = db.command +const userTable = db.collection('uni-id-users') +exports.main = async (event, context) => { + //执行业务逻辑 + let res = await sendSms(event.before_id) + if (res.errCode) { + return res + }else{ + // 如果没有报错,就让当å‰äº‘函数 调用当å‰äº‘函数(云对象åŒç†ï¼‰ã€‚注æ„:这里是异æ¥çš„ + uniCloud.callFunction({ + name: 'send-sms-cf', + data: { + before_id: res.before_id + } + }).catch(e=>{ + console.log(e.message); + }).then(e=>{ + console.log(e.result); + }) + + // ç‰å¾…500毫秒,给一个请求å‘出去的时间 + return await new Promise((resolve, reject) => { + setTimeout(() => { + resolve(res) + }, 500) + }) + } + + async function sendSms(before_id) { + console.log('before_id',before_id); + let where = { + phone: dbCmd.exists(true), + //..这里å¯ä»¥å†™ä½ 自己的其他æ¡ä»¶ï¼Œå¦‚超过多久没登录的用户 last_login_date < Date.now() - 3600*24*... + } + if(before_id){ + //高性能分页查询,以上一次查询的最åŽä¸€æ¡æ•°æ®çš„id被起始id + where._id = dbCmd.gt(before_id) + } + + let res = await userTable.where(where) + .limit(50) + .orderBy("_id", "asc") + .get() + + if (!res.data.length) { + return { + errCode: 'sendSms-invalid', + errMsg: '结æŸï¼Œæ²¡æœ‰ç¬¦åˆæ¡ä»¶çš„接收者' + } + } + let phoneList = res.data.map(item => item.phone) + res = await uniCloud.sendSms({ + phoneList, + appid: '__UNI__xxxxxxx', + smsKey: '****************', + smsSecret: '****************', + templateId: '100**', // 请替æ¢ä¸ºè‡ªå·±ç”³è¯·çš„模æ¿id + data: { + text1: 'xxx', + text2: 'xxx' + } + }) + if (res.errCode) { + return res + } + return { + errCode: 0, + before_id: res.data[res.data.length - 1]._id + } + } +}; +``` + +注æ„:如果ä¸å°å¿ƒæŠŠé€’归云函数写æˆæ»å¾ªçŽ¯ï¼Œå°±æŠŠäº‘å‡½æ•°çš„å†…å®¹å…¨éƒ¨åˆ é™¤ï¼Œé‡æ–°ä¸Šä¼ 覆盖å³å¯ + + +### 云函数内访问其他æœåŠ¡ç©ºé—´@call-by-function-cross-space + +> ä»…è…¾è®¯äº‘æ”¯æŒ + +在腾讯云æœåŠ¡ç©ºé—´çš„云函数内支æŒèŽ·å–**åŒè´¦å·**下其他æœåŠ¡ç©ºé—´çš„uniCloud实例,å‚考:[一个应用访问多个æœåŠ¡ç©ºé—´](uniCloud/concepts/space.md?id=multi-space),并使用æ¤å®žä¾‹è°ƒç”¨å¯¹åº”æœåŠ¡ç©ºé—´çš„云函数。 + +```javascript +//å¼€å‘者创建了多个æœåŠ¡ç©ºé—´ï¼Œåˆ™éœ€æ‰‹åŠ¨åˆå§‹åŒ–。注æ„这是å‰ç«¯ä»£ç ,ä¸æ˜¯äº‘函数代ç +const myCloud = uniCloud.init({ + provider: 'tencent', + spaceId: 'xxxx-yyy' +}); +//通过uniCloud实例调用云开å‘çš„API +myCloud.callFunction() +myCloud.uploadFile() +``` + +**注æ„** + +- 连接本地云函数调试时,如果å˜åœ¨è·¨æœåŠ¡ç©ºé—´è°ƒç”¨ï¼Œåˆ™callFunction会使用云端云函数 + +## serverless环境说明@runtime + +serverless是动æ€åˆ†åˆ«è®¡ç®—资æºçš„,由æ¤ä¼šå¼•å‘的出一批特有概念:冷å¯åŠ¨ã€å®žä¾‹ã€å¹¶å‘请求ã€æ— 状æ€ã€ä¼ªå…¨å±€å˜é‡ã€‚ + +### 云函数冷å¯åŠ¨ã€çƒå¯åŠ¨@launchtype + +基于云函数按需执行的特点, 函数在ä¸è¢«è§¦å‘的时候, 计算资æºæ˜¯ä¸è¢«æ¿€æ´»çš„。 + +当一个云函数åˆæ¬¡è¢«è§¦å‘时,其完整过程如下: + +1. severless实例化计算实例 +2. åŠ è½½å‡½æ•°ä»£ç +3. å¯åŠ¨ node +4. 执行云函数代ç + +函数被调用时,执行这些完整æ¥éª¤çš„过程称作`冷å¯åŠ¨`, 冷å¯åŠ¨çš„耗时一般在一秒左å³ã€‚ + +一个云函数实例冷å¯åŠ¨åŽï¼Œserverless调度ä¸å¿ƒä¼šä¿ç•™è¿™ä¸ªå®žä¾‹ä¸€å®šæ—¶é—´ã€‚在实例ä¿ç•™æœŸé—´ï¼Œå®¢æˆ·ç«¯å†æ¬¡è¯·æ±‚云函数,ä¸ä¼šè§¦å‘冷å¯åŠ¨ï¼Œé€Ÿåº¦ä¼šæ›´å¿«ã€‚实例的详细定义[è§ä¸‹](#instance) + +云函数实例和执行进程都被å¤ç”¨çš„情况下称之为`çƒå¯åŠ¨`, çƒå¯åŠ¨æ€§èƒ½è¦å¥½éžå¸¸å¤šï¼Œå› 为它åªæœ‰ä¸€ä¸ªæ¥éª¤ï¼š +1. 执行云函数代ç + +如果一个云函数实例长时间没有被å†æ¬¡è°ƒç”¨ï¼Œåˆ™è¯¥è®¡ç®—实例会被**回收**ï¼›åŽç»å†æ¬¡è°ƒç”¨è¯¥äº‘函数时,就会å†æ¬¡è§¦å‘云函数的**冷å¯åŠ¨**。 + +ä¸åŒäº‘厂商的函数实例回收时间ä¸åŒï¼š +- 阿里云:15分钟内没有第二次访问的云函数,就会被回收 +- 腾讯云:30分钟 + +直观的体验表现为:隔了很久ä¸ç”¨çš„云函数,第一次用就会比较慢,然åŽç«‹å³è®¿é—®ç¬¬äºŒæ¬¡ï¼Œåˆ™å¾ˆå¿«ï¼Œæ¯«ç§’级å“应。 + +注:冷å¯åŠ¨è™½æ…¢ä½†ä¹Ÿä¸ä¼šè¶…过1.5秒,如超过1.5秒应该是云函数写的有问题或网络有问题。 + +两家云厂商ä»ç„¶åœ¨ä¼˜åŒ–冷å¯åŠ¨é—®é¢˜ã€‚ç›®å‰ç»™å¼€å‘者的建议是: +1. 使用clientDBå¯ä»¥å‡å°‘é‡åˆ°å†·å¯åŠ¨é—®é¢˜çš„概率 +2. éžé«˜é¢‘访问的云函数,åˆå¹¶åˆ°é«˜é¢‘云函数ä¸ã€‚也有的开å‘者使用å•è·¯ç”±æ–¹å¼ç¼–写云函数,å³åœ¨ä¸€ä¸ªäº‘函数ä¸é€šè¿‡è·¯ç”±å¤„ç†å®žçŽ°äº†æ•´ä¸ªåº”用的所有åŽå°é€»è¾‘。å‚考[æ’件](https://ext.dcloud.net.cn/search?q=%E8%B7%AF%E7%94%B1&cat1=7&orderBy=UpdatedDate)。 + 但使用这ç§æ–¹å¼éœ€æ³¨æ„平衡,如果业务代ç 太多,æ¯æ¬¡äº‘函数请求产生的内å˜æ¶ˆè€—也会ä¸å°‘。 +3. éžé«˜é¢‘访问的云函数,å¯ä»¥é€šè¿‡å®šæ—¶ä»»åŠ¡æŒç»è¿è¡Œå®ƒï¼ˆæ³¨æ„腾讯云å¯ä»¥ä½¿ç”¨è¿™ä¸ªæ–¹å¼å®Œå…¨é¿å¼€å†·å¯åŠ¨ï¼Œè€Œé˜¿é‡Œäº‘的定时任务最çŸå‘¨æœŸå¤§äºŽèµ„æºå›žæ”¶å‘¨æœŸï¼‰ +4. 阿里云支æŒé…置云函数的å•å®žä¾‹å¤šå¹¶å‘,请å‚考:[å•å®žä¾‹å¤šå¹¶å‘](cf-functions.md?id=concurrency) +5. 腾讯云付费进行实例预留 + +### 实例与请求@instance + +`实例`,指云函数的一个执行环境,å¯ä»¥ç®€å•çš„ç†è§£ä¸ºä¸€ä¸ªnode进程。 + +æ¯æ¬¡å®¢æˆ·ç«¯å‘èµ·`请求`(request)时,serverless的调度ä¸å¿ƒä¼šæŸ¥çœ‹å·²å¯åŠ¨ã€ä¸”空闲的实例,分é…一个实例æ¥æŽ¥æ”¶è¿™ä¸ªè¯·æ±‚。如果没有空闲实例,则新起一个实例。 + +新起一个实例需è¦ä¸€å®šæ—¶é—´ï¼Œä¹Ÿå³ä¸Šæ–‡è¯´çš„冷å¯åŠ¨é—®é¢˜ã€‚详è§[冷å¯åŠ¨](#launchtype) + +一个实例å¯åŠ¨åŽï¼Œä¸€èˆ¬åœ¨1秒内就会完æˆè¯·æ±‚,但serverless调度ä¸å¿ƒä¼šä¿ç•™è¿™ä¸ªå®žä¾‹ä¸€å®šæ—¶é—´ï¼ˆæ—¶é—´è§ä¸Šä¸€èŠ‚)。在实例ä¿ç•™æœŸé—´ï¼Œå®¢æˆ·ç«¯å†æ¬¡è¯·æ±‚云函数,ä¸ä¼šè§¦å‘冷å¯åŠ¨ã€‚ + +也就是说,**在实例ä¿ç•™æœŸé—´ï¼Œ1个实例会接å—多个客户端请求。** + +所以è¦æ³¨æ„`实例`å’Œ`请求`ä¸æ˜¯ä¸€å¯¹ä¸€å…³ç³»ã€‚ + +`请求`(request),指一次连接云函数的网络请求。ä¸åŒè¯·æ±‚有ä¸åŒçš„上下文信æ¯ï¼ˆæ¯”如客户端UA)。 + +所以想è¦èŽ·å–客户端信æ¯ï¼Œä¸€å®šæ³¨æ„ä¸æ˜¯åœ¨å®žä¾‹çš„全局对象上获å–,而是需è¦åœ¨è¯·æ±‚的上下文ä¸èŽ·å–。[详è§]() + +在uniCloud阿里云版,阿里云还æ供了1个实例的多并å‘请求é…置,å³åŒä¸€æ—¶é—´å¤šä¸ªè¯·æ±‚å¯ä»¥å¹¶å‘执行。 +也就是åŒä¸€æ—¶é—´çš„请求å‘到云函数时,没有é…ç½®å•å®žä¾‹å¤šå¹¶å‘会新开一个云函数实例,é…置了å•å®žä¾‹å¤šå¹¶å‘则ä¸ä¼šæ–°å¼€å®žä¾‹ï¼Œåœ¨ä¸€ä¸ªå®žä¾‹ä¸å¢žåŠ 并å‘。 +详è§[å•å®žä¾‹å¤šå¹¶å‘](#concurrency)。 + +一个云函数,å¯ä»¥åŒæ—¶å˜åœ¨å¤šä¸ªå®žä¾‹ã€‚比如cf1云函数,如未é…ç½®å•å®žä¾‹å¤šå¹¶å‘,10个请求åŒæ—¶è¾¾åˆ°äº‘函数,就会开10个实例。 + +ä¸ç®¡å¼€äº†å¤šå°‘实例,云函数的计费是按请求计费的。实例å“应请求åŽåˆ°ä¿ç•™æœŸç»“æŸä¹‹é—´ï¼Œå¦‚æžœä¸å‘生新请求是ä¸ä¼šè®¡è´¹çš„。 + +### äº‘å‡½æ•°çš„æ— çŠ¶æ€å’Œå…¨å±€å˜é‡@state-less + +å› ä¸ºå®žä¾‹å¯èƒ½ç¬¬ä¸€æ¬¡å¯åŠ¨ï¼Œä¹Ÿå¯èƒ½å·²ç»å¯åŠ¨ï¼Œæ‰€ä»¥äº‘函数ä¸çš„js全局å˜é‡å…¶å®žæ˜¯ä¼ªå…¨å±€å˜é‡ã€‚也就是**äº‘å‡½æ•°æ˜¯æ— çŠ¶æ€çš„**。 + +在云函数ä¸ï¼Œå†™åœ¨`module.exports = {}`之å‰ï¼Œäº‘函数写在`exports.main = async (event, context) => {}`之å‰çš„å˜é‡å®šä¹‰ï¼Œæ˜¯ä¼ªå…¨å±€å˜é‡ã€‚ + +它们在实例有效期内的多次请求ä¸ä¼šå¤ç”¨ã€‚ + +以如下代ç 为例,`count`作为全局å˜é‡ï¼Œå½“多次调用该云函数时,å¯èƒ½ä¼šå‡ºçŽ°å˜é‡ç´¯åŠ 的情况。 + +- 云对象示例 +```js +let count = 0; +module.exports = { + methoda() { + return count++ + } +} +``` + +- 云函数示例 + +```javascript +let count = 0; +exports.main = async (event, context) => { + return count++ +} +``` + +上é¢2个示例ä¸ï¼Œå®žä¾‹æœªå¤ç”¨æ—¶ï¼Œä¹Ÿå°±æ˜¯å†·å¯åŠ¨æ—¶ï¼Œcount的值æ¯æ¬¡éƒ½æ˜¯0;若实例被å¤ç”¨ï¼Œåˆ™å¯èƒ½è¿”回1ã€2ã€3ç‰å„ç§æ„外情况。 + +当然,å¯ä»¥ç”¨è¿™ä¸ªæ–¹æ³•æ¥èŽ·çŸ¥ä¸€ä¸ªå®žä¾‹è¢«é‡ç”¨äº†å¤šå°‘次请求。 + +**require由于å˜åœ¨ç¼“å˜ï¼Œä¹Ÿå˜åœ¨åŒæ ·çš„问题。尽é‡ä¸è¦ç›´æŽ¥ä¿®æ”¹require返回的内容。** + +**uniCloud全局对象也是跨请求的,与请求相关的内容ä¸åº”该挂载到uniCloud全局对象上。** + +**æ£ç¡®çš„全局å˜é‡ï¼Œåº”该使用如下方案:** +- uni-config-center:é™æ€å…¨å±€å˜é‡å¯ä»¥ä½¿ç”¨uniæ供的é…ç½®ä¸å¿ƒã€‚[详è§](uni-config-center.md) +- redis:动æ€å…¨å±€å˜é‡ä½¿ç”¨redis。[详è§](redis-introduction.md) + +### 请求的上下文 + +由于上节æ到的,uniCloud全局对象是实例级的ã€è·¨è¯·æ±‚的,1个实例内uniCloudåªä¼šåœ¨å†·å¯åŠ¨æ—¶è¿›è¡Œä¸€æ¬¡åˆå§‹åŒ–。 + +所以与请求相关的上下文,比如客户端信æ¯ï¼Œéœ€è¦é€šè¿‡è¯·æ±‚æ¥èŽ·å–。 + +为了让开å‘者清晰的了解实例和请求的关系,uniCloudæ供了如下方案。 + +1. 通过uniCloud.getRequestList(),å¯ä»¥èŽ·å¾—当å‰å®žä¾‹çš„请求id列表 +æ¯ä¸ªè¯·æ±‚,都有一个requestId,在è¿è¡Œå›žè°ƒé‡Œã€äº‘端日志里都有体现。 +```js +uniCloud.getRequestList() +// 返回值:['3228166e-3c17-4d58-9707-xxxxxxxx'] +``` + + - 如果未é…置阿里云的å•å®žä¾‹å¤šå¹¶å‘,getRequestList()返回的数组里é¢åªæœ‰ä¸€é¡¹ï¼Œå³åªèƒ½æ‹¿åˆ°å½“å‰çš„请求id。 + - 如果é…置了阿里云的å•å®žä¾‹å¤šå¹¶å‘,当并å‘å‘生时,这个列表就会返回多项,当å‰å¹¶å‘çš„æ¯ä¸ªrequestId都在里é¢ã€‚ + +2. uniCloud.getClientInfos(),å¯ä»¥è¿”回当å‰æ‰€æœ‰è¯·æ±‚的客户端信æ¯ã€‚ +该方法返回一个数组,当å‰æ¯ä¸ªå¹¶å‘执行ä¸çš„请求的客户端信æ¯éƒ½åœ¨é‡Œé¢ã€‚ +```json +[ + { + "appId": "__UNI_xxxxx", + "requestId": "3228166e-3c17-4d58-9707-xxxxxxxx" + // ... + } +] +``` + + - 如果未é…置阿里云的å•å®žä¾‹å¤šå¹¶å‘,getRequestList()返回的数组里é¢åªæœ‰ä¸€é¡¹ï¼Œå³åªèƒ½æ‹¿åˆ°å½“å‰çš„请求id。 + - 如果é…置了阿里云的å•å®žä¾‹å¤šå¹¶å‘,当并å‘å‘生时,这个列表就会返回多项,当å‰å¹¶å‘çš„æ¯ä¸ªrequestId都在里é¢ã€‚ + +3. + +如果是uniCloudç§æœ‰äº‘, +如果想获å–与请求相关的信æ¯ï¼Œæ¯”如这次请求的客户端UA,或云函数环境信æ¯ï¼Œæ— 法直接在uniCloud全局对象ä¸èŽ·å–。 + + +云函数入å£å…¥å‚包å«ä¸€ä¸ªevent和一个context,这两个å‚数和请求相关,æ¯æ¬¡æœ‰æ–°è¯·æ±‚到云函数实例时就会有一个新的event对象和一个新的context对象 + +云对象的thiså’Œeventã€context类似,æ¯ä¸ªè¯·æ±‚都对应一个å•ç‹¬çš„this。 + +### å•å®žä¾‹å¤šå¹¶å‘@concurrency + +> ä»…é˜¿é‡Œäº‘æ”¯æŒ + +默认情况下云函数仅支æŒå•å®žä¾‹å•å¹¶å‘,å³åŒä¸€æ—¶é—´ä¸€ä¸ªå®žä¾‹ä»…å¯ä¸ºä¸€ä¸ªè¯·æ±‚æœåŠ¡ï¼ˆä¸åŒè¯·æ±‚åŒä¸€æ—¶é—´è®¿é—®ä¼šè¢«åˆ†æ´¾åˆ°ä¸åŒå®žä¾‹è¿›è¡Œå¤„ç†ï¼‰ã€‚ä¸è¿‡åœ¨uniCloud web控制å°ä¸ï¼Œé˜¿é‡Œäº‘å¯ä»¥é€šè¿‡ä¿®æ”¹äº‘函数å•å®žä¾‹å¹¶å‘度,å¯ä»¥ä¿®æ”¹äº‘函数åŒä¸€æ—¶é—´æœ€å¤šèƒ½å¤„ç†å¤šå°‘请求。 + +å‡è®¾åŒæ—¶æœ‰3个请求需è¦å¤„ç†ï¼š + +当实例并å‘度设置为1时,需è¦åˆ›å»º3个实例æ¥å¤„ç†è¿™3个请求,æ¯ä¸ªå®žä¾‹åˆ†åˆ«å¤„ç†1个请求。而æ¯å¼€å¯ä¸€ä¸ªå®žä¾‹éƒ½ä¼šå¼•å‘云函数冷å¯åŠ¨ï¼› + +当云函数的实例并å‘度设置为10时(å³1个实例å¯ä»¥åŒæ—¶å¤„ç†10个请求),åªéœ€è¦åˆ›å»º1个实例就能处ç†è¿™3ä¸ªè¯·æ±‚ã€‚è¿™æ ·åŽé¢2个并å‘请求ä¸ä¼šæœ‰å› 云函数实例创建带æ¥çš„冷å¯åŠ¨é—®é¢˜ã€‚ + +相关文档:[云函数实例åŠéƒ¨åˆ†å˜é‡è¯´æ˜Ž](#instance) ã€[äº‘å‡½æ•°çš„æ— çŠ¶æ€](#state-less) + +**å¼€å¯æ–¹å¼** + +云函数详情页é¢é…ç½®å•å®žä¾‹å¹¶å‘度å³å¯ï¼Œæ”¯æŒ1-100之间的数值 + +**效果** + +- 有效å‡å°‘并å‘请求时云函数冷å¯åŠ¨æ¬¡æ•° + +**使用注æ„** + +- 虽然阿里云云函数支æŒé…置多并å‘,但在高并å‘下异æ¥è¯·æ±‚排队效果未必好于新开一个实例。尤其是并å‘æ“作数æ®åº“性能ä¸ä½³ã€‚**一般情况下ä¸è¦è®¾ç½®è¿‡å¤§çš„并å‘度,å¯ä»¥è‡ªå·±é’ˆå¯¹ä¸šåŠ¡ä»£ç 测试比较下是å¦å¯ç”¨å¹¶å‘或并å‘æ•°é…æˆå¤šå°‘** +- 云函数内å˜ä½¿ç”¨é‡ä¼šéšç€å¹¶å‘é‡å¢žå¤§è€Œå¢žåŠ ,过大的内å˜å¯èƒ½å¯¼è‡´OOM +- 注æ„云函数是有超时时间的。设置过大的å•å®žä¾‹å¤šå¹¶å‘å¯èƒ½ä¼šå¯¼è‡´å®žä¾‹åº•å±‚网络请求排队从而导致请求超时, +- 如果并å‘çš„ä¸åŒè¯·æ±‚对全局å˜é‡åŒæ—¶è¿›è¡Œè¯»å†™ä¼šæ±¡æŸ“全局å˜é‡ï¼Œå¯èƒ½ä¼šå¯¼è‡´æ„想ä¸åˆ°çš„åŽæžœï¼Œè¯¦è§[全局å˜é‡](#state-less) + +**适用场景** + +|场景 |适用性 |ç†ç”± | +|:-: |:-: |:-: | +|函数ä¸æœ‰è¾ƒå¤šæ—¶é—´åœ¨ç‰å¾…下游æœåŠ¡çš„å“应 |适用 |ç‰å¾…å“应一般ä¸æ¶ˆè€—资æºï¼Œåœ¨ä¸€ä¸ªå®žä¾‹å†…并å‘处ç†å¯ä»¥èŠ‚çœè´¹ç”¨ã€‚ | +|函数ä¸æœ‰å…±äº«çŠ¶æ€ä¸”ä¸èƒ½å¹¶å‘访问 |ä¸é€‚用 |例如全局å˜é‡ï¼Œå¤šè¯·æ±‚并å‘执行修改共享状æ€å¯èƒ½ä¼šå¯¼è‡´é”™è¯¯ã€‚ | +|å•ä¸ªè¯·æ±‚的执行è¦æ¶ˆè€—大é‡CPUåŠå†…å˜èµ„æº |ä¸é€‚用 |多请求并å‘æ‰§è¡Œä¼šé€ æˆèµ„æºäº‰æŠ¢ï¼Œå¯èƒ½ä¼šå¯¼è‡´å†…å˜ä¸è¶³ï¼ˆOOMï¼‰æˆ–è€…å»¶æ—¶å¢žåŠ ã€‚ | + +**关于旧版本uni-id公共模å—的特殊说明** + +旧版本uni-id公共模å—指uni-id-common推出之å‰çš„版本。[详è§](uni-id.md) + +```js +// å¼€å¯å•å®žä¾‹å¤šå¹¶å‘å‰çš„uni-id用法 +const uniID = require('uni-id') +exports.main = async function(event, context) { + const res = uniID.login({ + // ...一些å‚æ•° + }) + return res +} + +// 由于uni-id默认会从一个内置全局å˜é‡ä¸ŠèŽ·å–客户端平å°ä¿¡æ¯ï¼Œä¸åŒè¯·æ±‚会修改æ¤å…¨å±€å˜é‡å¯èƒ½é€ æˆæ··ä¹±ï¼Œå¼€å¯å•å®žä¾‹å¤šå¹¶å‘åŽéœ€è¦å°†uni-id修改为如下写法 +let uniID = require('uni-id') +exports.main = async function(event, context) { + let uniIDIns = uniID.createInstance({ // 创建uni-id实例,其上方法åŒuniID + context: context // ä¼ å…¥context防æ¢ä¸åŒè¯·æ±‚äº’ç›¸å½±å“ + // config: {} // 完整uni-idé…置信æ¯ï¼Œä½¿ç”¨config.json进行é…ç½®æ—¶æ— éœ€ä¼ æ¤å‚æ•° + }) + const res = uniIDIns.login({ + // ...一些å‚æ•° + }) + return res +} +``` + +ä¸åŒäºŽæ—§ç‰ˆuni-id公共模å—,新版uni-id-commonä¸å¯ç›´æŽ¥requireåŽä½¿ç”¨ï¼Œå¿…须使用createInstance方法 + +**进阶** + +å¼€å¯å•å®žä¾‹å¤šå¹¶å‘åŽçš„全局å˜é‡å¤ç”¨å¹¶éžä¸€å®šæ˜¯åçš„ç»“æžœï¼Œå¦‚æžœä½ å¾ˆäº†è§£æ¤è¡Œä¸ºï¼Œä¹Ÿå¯ä»¥å¯¹æ¤è¿›è¡Œæœ‰æ•ˆçš„利用 + +例:[ip-filter](https://ext.dcloud.net.cn/plugin?id=4619)ä¸å°±åˆ©ç”¨äº‘函数全局缓å˜ä¸€äº›ip访问信æ¯æ¥é™åˆ¶å•ip访问频率,å¯ä»¥ä¸‹è½½ç¤ºä¾‹é¡¹ç›®ä½“验一下 + +å—å•å®žä¾‹å¤šå¹¶å‘çš„å½±å“,云函数全局å˜æ”¾ä¸Žæœ¬æ¬¡è¯·æ±‚有关的信æ¯ä¼šé€ æˆæ··ä¹±ã€‚å› æ¤uniCloudæä¾›äº†æ ¹æ®å½“å‰requestId获å–客户端信æ¯å’Œäº‘端信æ¯ã€‚å‚考以下文档 + +- [云函数获å–当å‰requestId](cf-callfunction.md#context) +- [云对象获å–当å‰requestId](cloud-obj.md#get-request-id) +- [获å–当å‰äº‘函数实例æ£åœ¨å¤„ç†çš„请求对应的requestId列表](#get-request-list) +- [获å–当å‰äº‘函数实例æ£åœ¨å¤„ç†çš„请求对应的客户端信æ¯åˆ—表](#get-client-infos) +- [获å–当å‰äº‘函数实例æ£åœ¨å¤„ç†çš„请求对应的云端信æ¯åˆ—表](#get-cloud-infos) + + +### 临时å˜å‚¨ç©ºé—´ + +云函数是è¿è¡Œåœ¨äº‘端的代ç ,è¿è¡ŒçŽ¯å¢ƒç”±äº‘æœåŠ¡å™¨å¼¹æ€§è°ƒé…ï¼Œè¿™æ˜¯å’Œä¼ ç»Ÿ`Node.js`应用很大的区别。 + +æ¢è¨€ä¹‹ï¼Œäº‘函数æ¯æ¬¡æ‰§è¡Œçš„宿主环境(å¯ç®€å•ç†è§£ä¸ºè™šæ‹Ÿæœºæˆ–æœåŠ¡å™¨ç¡¬ä»¶ï¼‰å¯èƒ½ç›¸åŒï¼Œä¹Ÿå¯èƒ½ä¸åŒï¼Œå› æ¤ä¼ 统`Node.js`å¼€å‘ä¸å°†éƒ¨åˆ†ä¿¡æ¯å˜å‚¨æœ¬åœ°ç¡¬ç›˜æˆ–内å˜çš„方案就ä¸å†é€‚åˆã€‚ + +所以,ä¸å»ºè®®ä½¿ç”¨nodeçš„fs文件系统相关的API。建议通过云数æ®åº“ã€äº‘å˜å‚¨ã€redis的方案替代。 + +### 云函数ä¸çš„异æ¥è¡Œä¸º + +书写云函数时应注æ„`async`ã€`await`的使用,`nodejs`有内置模å—`util`å¯ä»¥å°†ç¬¦åˆ`error-first`å½¢å¼`callback`的函数转æ¢ä¸º`promise`å½¢å¼ï¼Œ[详情å‚考](https://nodejs.org/api/util.html#util_util_promisify_original),比如以下示例: + +```js +const { + promisify +} = require('util') + +let testCallback = { + value: 'testCallbackValue', + echo: function(num, callback) { + setTimeout(() => { + // 第一个å‚数为error,第二个为返回值 + callback(null, `${this.value}:${num}`) + }, 2000) + } +} + +exports.main = async function() { + // num=2,ä¸ä¼ å…¥callbackå‚数,callbackä¼šè‡ªåŠ¨ä½œä¸ºå›žè°ƒå‡½æ•°å¤„ç† + let val = await promisify(testCallback.echo).call(testCallback, 2) + console.log(val) + return val +} + +``` + +如果想在云函数内使用回调形å¼å¯ä»¥è®©äº‘函数返回一个promise,如以下示例: + +```js +exports.main = async function() { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve('some return value') + }, 1000) + }) +} +``` + + +### returnçš„ç–ç•¥@return + +- 阿里云 return 之åŽäº‘函数立å³ç»ˆæ¢ï¼Œé€»è¾‘ä¸ä¼šç»§ç»æ‰§è¡Œï¼ŒåŒ…括 settimeout 或其他异æ¥æ“作都会立å³ç»ˆæ¢ã€‚ +- 腾讯云 node8 return 之åŽä¹Ÿä¸ä¼šç»§ç»æ‰§è¡Œï¼Œä½† node12 å¯ä»¥é…置是å¦ç»§ç»æ‰§è¡Œ +- HBuilderX 本地è¿è¡Œ + * ä¸é€šè¿‡å®¢æˆ·ç«¯å‘起,直接本地è¿è¡Œäº‘函数/云对象,return 之åŽè¿˜å¯ä»¥æ‰§è¡Œ300ms + * 通过客户端连接本地云函数/云对象,return 之åŽå¯ä»¥ç»§ç»æ‰§è¡Œ + +**è…¾è®¯äº‘å› ä¸ºæŒ‰ GBS 对云函数计费,在 node12 时,尤其è¦æ³¨æ„,如果未有效终æ¢äº‘函数,会一直计费** + +### node版本 +云函数è¿è¡Œåœ¨ node 环境ä¸ã€‚å¯ä»¥ä½¿ç”¨ node api `process.version` èŽ·å– node 版本。 + +- uniCloud 阿里云默认是 node8.17.0,也å¯ä»¥åœ¨ package.json ä¸é€‰æ‹© node12 +- uniCloud 腾讯云默认是 node8.9.4,也å¯ä»¥åœ¨ package.json ä¸é€‰æ‹© node12 +- HBuilderX 本地è¿è¡ŒçŽ¯å¢ƒä½¿ç”¨çš„是 HBuilderX 自带的 node 版本,目å‰ä¸º node12。在 package.json 选择 node版本 åªäº‘端生效,且åªåœ¨ç¬¬ä¸€æ¬¡ä¸Šä¼ 云函数时生效。 + +**注æ„** +- 本地开å‘一旦使用了 node12 的专用 apiï¼Œä¸Šä¼ äº‘å‡½æ•°æ—¶å¿…é¡»åœ¨package.json里手动é…置选择 node12 çš„è¿è¡ŒçŽ¯å¢ƒã€‚ + 之所以没有在云端默认统一使用 node12ï¼Œæ˜¯å› ä¸ºè…¾è®¯äº‘ node12 çš„ return ç–略有一些特殊情况,[è§ä¸‹](?id=return)。 +- è¿è¡ŒçŽ¯å¢ƒåœ¨äº‘端云函数创建时设定,ä¸å¯é€šè¿‡æ›´æ–°äº‘函数æ¥ä¿®æ”¹ã€‚ + ä¹Ÿå°±æ˜¯ç¬¬ä¸€æ¬¡ä¸Šä¼ äº‘å‡½æ•°çš„æ—¶å€™ï¼Œpackage.json里é…了什么,就是什么。如果需è¦ä¿®æ”¹nodeçŽ¯å¢ƒï¼Œéœ€å…ˆåˆ é™¤äº‘ç«¯äº‘å‡½æ•°ï¼Œé‡æ–°ä¸Šä¼ 。 + +node版本å¯ä»¥åœ¨äº‘函数的package.json文件的`cloudfunction-config->runtime`å—段进行é…置,详情å‚考:[云函数package.json](uniCloud/cf-functions.md?id=packagejson) + + +### 时区 + +云端的云函数ä¸ä½¿ç”¨çš„时区是 `UTC+0`,而ä¸æ˜¯ `UTC+8`,在云函数ä¸ä½¿ç”¨æ—¶é—´æ—¶éœ€ç‰¹åˆ«æ³¨æ„。 + +云函数在HBuilderX本地è¿è¡Œæ—¶ï¼Œæ—¶åŒºåˆ™æ˜¯ç”µè„‘的时区,很å¯èƒ½æ˜¯ `UTC+8`。建议统一使用时间戳,å¯ä»¥è§„é¿æ—¶åŒºé—®é¢˜ã€‚ + +## 云函数é…ç½® + +云函数除了代ç ,还有é…置。在uniCloud web控制å°å¯ä»¥é…置;在HBuilderX项目ä¸ï¼Œäº‘å‡½æ•°æ ¹ç›®å½•çš„`package.json`也是å˜æ”¾é…置的地方。 + +### 超时时间@timeout + +阿里云éžå®šæ—¶è§¦å‘请求云函数最大åªæ”¯æŒ10秒的超时时间。定时任务触å‘最大支æŒ600秒的超时时间,一般用于跑批。 + +腾讯云最大支æŒ900秒超时时间 + +如果超时时间ä»ç„¶ä¸å¤Ÿç”¨ï¼Œå¯ä»¥å‚考云函数递归调用,连ç»æ‰§è¡Œå¤šä¸ªäº‘函数处ç†ä¸€ä¸ªä»»åŠ¡[详情查看](uniCloud/cf-functions.md?id=recurrence) + +### 固定出å£IP@eip + +#### 腾讯云@tencent-eip + +serverless默认是没有固定的æœåŠ¡å™¨IPçš„ï¼Œå› ä¸ºæœ‰å¾ˆå¤šæœåŠ¡å™¨èµ„æºåœ¨åŽå°ä¾›éšæ—¶è°ƒç”¨ï¼Œæ¯æ¬¡è°ƒç”¨åˆ°å“ªä¸ªæœåŠ¡å™¨ã€å“ªä¸ªip都ä¸å›ºå®šã€‚ + +但一些三方系统,è¦æ±‚é…置固定ip白åå•ï¼Œæ¯”如微信公众å·çš„js sdk,æ¤æ—¶åªèƒ½æ供固定ip地å€ã€‚ + +ç›®å‰è…¾è®¯äº‘的收费版,æ供了云函数的固定出å£ip + +在uniCloud [Web控制å°](https://unicloud.dcloud.net.cn),创建付费的腾讯云æœåŠ¡ç©ºé—´ï¼Œé€‰æ‹©ä¸€ä¸ªäº‘函数,在云函数的详情界é¢å¯ä»¥å¼€å¯å›ºå®šå‡ºå£ip。开å¯åŽç•Œé¢ä¸Šä¼šæ˜¾ç¤ºå¯ç”¨çš„固定ip。拿ç€è¿™ä¸ªip去需è¦å›ºå®šipçš„ç•Œé¢ï¼ˆå¦‚微信公众å·ç®¡ç†ç•Œé¢ï¼‰é…ç½®å³å¯ã€‚ + +**注æ„** + +- å¦‚æžœä½ æ˜¯å…费版å‡é…到付费版,开å¯`固定IP`功能åŽï¼Œä¼šå¯¼è‡´ä»˜è´¹ç‰ˆåˆ°æœŸæ— 法自动é™çº§åˆ°å…费版,请注æ„按时ç»è´¹ + +腾讯云原本的设计是åŒä¸€ä¸ªæœåŠ¡ç©ºé—´å†…所有开å¯å›ºå®šå‡ºå£IP的云函数使用的是åŒä¸€ä¸ªIP。但是对于开通vpcçš„äº‘å‡½æ•°æ— æ³•å’Œæœªå¼€é€švpc的函数共用åŒä¸€ä¸ªå‡ºå£ip。具体使用ä¸æœ‰ä»¥ä¸‹è¡¨çŽ° + +- 开通redis扩展的云函数和未开通redis扩展的云函数会分é…ä¸åŒçš„ip +- 如果一个云函数已ç»å¼€é€šå›ºå®šå‡ºå£ip,å†å…³è”redis扩展库时固定ip会å‘生å˜åŒ– + +建议已开通redisçš„æœåŠ¡ç©ºé—´å…ˆå°†äº‘函数关è”redis扩展å†å¼€é€šå›ºå®šå‡ºå£IP,**2022å¹´7月20æ—¥èµ·æ–°ä¸Šä¼ çš„äº‘å‡½æ•°ä¼šé»˜è®¤å¼€å¯vpc功能,如需旧云函数和新云函数ä¿æŒä¸€è‡´å¯ä»¥æŠŠæ—§äº‘函数关è”redis扩展åŽä¸Šä¼ 一次,注æ„è¿™æ ·æ“作会改å˜æ—§äº‘函数的固定出å£IP** + +#### 阿里云@aliyun-eip + +> 新增于 HBuilderX 3.5.5 + +uniCloud.httpProxyForEip ,其原ç†æ˜¯é€šè¿‡ä»£ç†è¯·æ±‚获得固定出å£IP的能力。IP为轮转ä¸å›ºå®šï¼Œå› æ¤ä¸‰æ–¹æœåŠ¡è¦æ±‚使用白åå•æ—¶å¼€å‘者需è¦å°†ä»£ç†æœåŠ¡å™¨å¯èƒ½çš„IPå‡åŠ 入到白åå•ä¸ï¼Œè§ä¸‹æ–¹ä»£ç†æœåŠ¡å™¨åˆ—表。æ¤å¤–对于代ç†çš„域å有é™åˆ¶ï¼Œå½“å‰ä»…æŒ`weixin.qq.com`泛域å。若开å‘者有其他域å代ç†éœ€æ±‚,å‘é€é‚®ä»¶åˆ°service@dcloud.io申请。 + +代ç†æœåŠ¡å™¨IP列表 + +``` +39.100.3.155 +47.92.39.39 +47.92.67.205 +47.92.25.106 +47.92.68.159 +``` + +如需在获å–微信公众å·access_token场景使用,请将上述ipé…置到`å¾®ä¿¡å…¬ä¼—å¹³å° -> 基本é…ç½® -> IP白åå•`内,相关链接:[微信公众平å°](https://mp.weixin.qq.com/) + +##### å‘é€Get请求@http-proxy-get + +**用法** + +```js +uniCloud.httpProxyForEip.get(url: String, params?: Object) +``` + +**示例** + +```js +await uniCloud.httpProxyForEip.get( + 'https://api.weixin.qq.com/cgi-bin/token', + { + grant_type: 'client_credential', + appid: 'xxxx', + secret: 'xxxx' + } +) +``` + +##### å‘é€POST请求æºå¸¦è¡¨å•æ•°æ®@http-proxy-post-form + +注æ„,æ¤æŽ¥å£ä»¥`application/x-www-form-urlencoded`æ ¼å¼å‘é€æ•°æ®è€Œä¸æ˜¯`multipart/form-data` + +**用法** + +```js +uniCloud.httpProxyForEip.postForm(url: String, data?: Object, headers?: Object) +``` + +**示例** + +```js +uniCloud.httpProxyForEip.postForm( + 'https://www.example.com/search', + { + q: 'nodejs', + cat: '1001' + } +) +``` + +##### å‘é€POST请求æºå¸¦JSONæ•°æ®@http-proxy-post-json + +以`application/json`æ ¼å¼postæ•°æ® + +**用法** + +```js +uniCloud.httpProxyForEip.postJson(url: String, json?: Object, headers?: Object) +``` + +**示例** + +```js +uniCloud.httpProxyForEip.postJson( + 'https://www.example.com/search', + { + q: 'nodejs', + cat: '1001' + } +) +``` + +##### POST通用数æ®@http-proxy-post + +**用法** + +```js +uniCloud.httpProxyForEip.post(url: String, text?: String, headers?: Object) +``` + +**示例** + +```js +uniCloud.httpProxyForEip.post( + 'https://www.example.com/search', + 'abcdefg', + { + "Content-Type": "text/plain" + } +) +``` + +**注æ„** + +- ä¸æ”¯æŒå‘é€multipartæ ¼å¼çš„内容 +- 代ç†è¯·æ±‚超时时间为5秒 +- 上述接å£æ”¯æŒæœ¬åœ°è¿è¡Œ + + +## 云函数package.json@packagejson + +HBuilderX 3.0版本之å‰ï¼Œpackage.jsonåªæ˜¯ä¸€ä¸ªæ ‡å‡†çš„package.json,安装ä¾èµ–或公共模å—æ‰éœ€è¦ã€‚HBuilderX 3.0åŠä»¥ä¸Šç‰ˆæœ¬ï¼Œpackage.json也å¯ä»¥ç”¨æ¥é…置云函数。 + +uniCloud web控制å°æ供了很多云函数的设置,比如内å˜å¤§å°ã€url化ã€å®šæ—¶è§¦å‘ç‰ï¼Œä»ŽHBuilderX 3.0起,在云函数的package.json里也å¯ä»¥ç¼–写这些设置。 + +å¼€å‘è€…åœ¨æœ¬åœ°ç¼–å†™äº‘å‡½æ•°çš„è®¾ç½®ï¼Œä¸Šä¼ äº‘å‡½æ•°ï¼Œè¿™äº›è®¾ç½®ä¼šè‡ªåŠ¨åœ¨äº‘ç«¯ç”Ÿæ•ˆã€‚ï¼ˆæœ¬åœ°ä¸ç”Ÿæ•ˆï¼‰ + +在云端设置了éžé»˜è®¤å‚æ•°åŽï¼ŒHBuilderX下载云函数到本地时,也会自动把设置项放入package.jsonä¸ä¸‹è½½ä¸‹æ¥ã€‚ + +package.jsonæ˜¯ä¸€ä¸ªæ ‡å‡†json文件,ä¸å¯å¸¦æ³¨é‡Šã€‚下é¢æ˜¯ä¸€ä¸ªpackage.json示例。 + +```json +{ + "name": "add-article", + "version": "1.0.0", + "description": "æ–°å¢žæ–‡ç« ", + "main": "index.js", + "dependencies": { + // 云函数的ä¾èµ–,包括公共模å—åŠè‡ªè¡Œå®‰è£…çš„npmä¾èµ– + }, + "extensions": { + // 云函数使用的扩展库 + }, + "cloudfunction-config": { + "memorySize": 256, + "timeout": 5, + "triggers": [{ + "name": "myTrigger", + "type": "timer", + "config": "0 0 2 1 * * *" + }], + "path": "", + "runtime": "Nodejs8" + } +} +``` + +### cloudfunction-config@cloudfunction-config + +å…¶ä¸cloudfunction-configå—段是云函数é…置,支æŒçš„é…置如下 + +```js +{ + "concurrency": 10, // å•ä¸ªäº‘函数实例最大并å‘é‡ï¼Œä¸é…置的情况下默认是1 + "memorySize": 256, // 函数的最大å¯ç”¨å†…å˜ï¼Œå•ä½MB,å¯é€‰å€¼ï¼š 128|256|512|1024|2048,默认值256 + "timeout": 5, // 函数的超时时间,å•ä½ç§’,默认值5。最长为60秒,阿里云在定时触å‘时最长å¯ä»¥æ˜¯600秒 + // triggers å—段是触å‘器数组,目å‰ä»…支æŒä¸€ä¸ªè§¦å‘器,å³æ•°ç»„åªèƒ½å¡«å†™ä¸€ä¸ªï¼Œä¸å¯æ·»åŠ 多个 + "triggers": [{ // 阿里云腾讯云å‡ä¸ºæ¤å½¢å¼ï¼Œè¯·é˜…读下方说明 + // name: 触å‘器的åå—,规则è§https://uniapp.dcloud.net.cn/uniCloud/trigger,nameä¸å¯¹é˜¿é‡Œäº‘生效 + "name": "myTrigger", + // type: 触å‘器类型,目å‰ä»…æ”¯æŒ timer (å³ å®šæ—¶è§¦å‘器),typeä¸å¯¹é˜¿é‡Œäº‘生效 + "type": "timer", + // config: 触å‘器é…置,在定时触å‘器下,config æ ¼å¼ä¸º cron 表达å¼ï¼Œè§„则è§https://uniapp.dcloud.net.cn/uniCloud/trigger。使用阿里云时会自动忽略最åŽä¸€ä½ï¼Œå³ä»£è¡¨å¹´ä»½çš„一ä½åœ¨é˜¿é‡Œäº‘ä¸ç”Ÿæ•ˆ + "config": "0 0 2 1 * * *" + }], + // 云函数Url化path部分,阿里云需è¦ä»¥/http/开头 + "path": "", + "runtime": "", // nodejs版本,å¯é€‰Nodejs8ã€Nodejs12,默认:Nodejs8 + "keepRunningAfterReturn": true // 是å¦åœ¨äº‘函数return之åŽç»§ç»æ‰§è¡Œï¼Œä»…腾讯云nodejs12生效,详情è§ä¸‹æ–¹è¯´æ˜Ž +} +``` + +**使用腾讯云Nodejs12版本时,务必仔细阅读æ¤æ–‡æ¡£ï¼š[keepRunningAfterReturn](#keep-running)** + +#### triggers@triggers + +阿里云定时触å‘çš„cron表达å¼ä¸æ”¯æŒä»£è¡¨å¹´çš„第七ä½ï¼Œä½†æ˜¯åœ¨package.json内é…置时ä»éœ€å°†ç¬¬ä¸ƒä½è®¾ç½®ä¸º*。 + +**在web控制å°é…ç½®trigger请å‚考:[定时触å‘](uniCloud/trigger.md)** + +package.json内统一了腾讯阿里的é…置,两个平å°éƒ½éœ€è¦é…ç½®ä¸ºå¦‚ä¸‹å½¢å¼ + +```js +{ + "name": "myTrigger", + "type": "timer", + "config": "0 0 2 1 * * *" +} +``` + +#### keepRunningAfterReturn@keep-running + +> 新增于HBuilderX 3.5.1 + +阿里云ã€è…¾è®¯äº‘nodejs8在云函数return之åŽå…¶ä½™é€»è¾‘会被冻结ä¸å†æ‰§è¡Œã€‚腾讯云nodejs12表现æ°å¥½ç›¸å,云函数return之åŽè¿˜ä¼šç‰å¾…其余逻辑执行åŽæ‰ä¼šå°†æ¤äº‘函数实例空闲出æ¥ã€‚ + +以下é¢çš„代ç 为例 + +```js +exports.main = async function(event, context) { + setTimeout(()=>{ + console.log('delay 5 seconds') + }, 5000) + return {} +} +``` + +如果æ¤äº‘函数è¿è¡Œåœ¨é˜¿é‡Œäº‘或腾讯云nodejs8,setTimeout里é¢çš„console.logä¸ä¼šåœ¨æœ¬æ¬¡äº‘函数调用执行,但是å¯èƒ½åœ¨äº‘函数实例å†æ¬¡è¢«å¤ç”¨æ—¶ç»§ç»æ‰§è¡Œã€‚ + +如果æ¤äº‘函数è¿è¡Œåœ¨è…¾è®¯äº‘nodejs12,setTimeout里é¢çš„console.log会在本次云函数调用内,åŒæ ·çš„本次云函数**计费时间(与云函数GBsæŒ‡æ ‡ç›¸å…³ï¼‰**也会按照最终执行完æˆçš„时间计算(5000ms+return耗时)。但是å‰ç«¯æ— 需ç‰å¾…5秒å³å¯æ”¶åˆ°å“应。注æ„:如果有未æ–开的长连接(例如:redis连接)会导致云函数一直è¿è¡Œåˆ°é…置的超时时间 + +当在云函数package.json内的cloudfunction-config内é…置了`keepRunningAfterReturn: false`时,å¯ä»¥æ”¹å˜è…¾è®¯äº‘nodejs12的表现,云函数return之åŽå°†ä¸å†ç»§ç»æ‰§è¡Œï¼Œæœªæ–开的长连接也ä¸ä¼šå¢žåŠ 云函数实际è¿è¡Œæ—¶é—´ï¼Œäº‘函数returnåŽé•¿è¿žæŽ¥ä¹Ÿä¸ä¼šè¢«ä¸æ–,简å•æ¥è¯´å…¶è¡¨çŽ°å’Œè…¾è®¯äº‘nodejs8一致。 + +**在云函数ä¸å‘é€ç½‘络请求** + +将上述示例ä¸çš„setTimeoutæ¢æˆç½‘络请求ã€è°ƒç”¨å…¶ä»–云函数或数æ®åº“请求åŒç†ï¼Œå¦‚果在阿里云或腾讯云nodejs8直接return会导致网络请求å¯èƒ½æ— 法å‘é€ï¼ˆå³ä½¿æˆåŠŸå‘é€ä¹Ÿæ˜¯åœ¨ä¸‹ä¸€æ¬¡äº‘函数实例被å¤ç”¨çš„æ—¶å€™ï¼‰ï¼Œè¿™æ˜¯ä¸Žä¼ ç»Ÿå¼€å‘ä¸å¤ªä¸€æ ·çš„地方。 + +```js +exports.main = async function(event, context) { + uniCloud.callFunction({ + name: 'test', + data: {} + }) + return {} // callFunctionåŽä¸ç‰å¾…直接returnæ—¶æ— æ³•è°ƒç”¨åˆ°test云函数 +} +``` + +**腾讯云nodejs12使用redis** + +由于redis需è¦å’ŒæœåŠ¡å™¨å»ºç«‹è¿žæŽ¥ï¼Œæ¤è¿žæŽ¥ä¼šé˜»æ¢äº‘函数结æŸæ‰§è¡Œã€‚如果没有云函数return之åŽè¿˜éœ€è¦ç»§ç»æ‰§è¡Œçš„需求,å¯ä»¥ç®€å•çš„在`cloudfunction-config`内é…ç½®`keepRunningAfterReturn: false`ã€‚è¿™æ ·redis的连接并ä¸ä¼šä¸æ–,下次请求æ¥æ—¶ä¾ç„¶å¯ä»¥ä½¿ç”¨ä¹‹å‰å»ºç«‹çš„连接。 + +如果需è¦return之åŽç»§ç»æ‰§è¡Œï¼Œé‚£ä¹ˆéœ€è¦åœ¨ä½¿ç”¨å®Œæ¯•åŽæ–å¼€redis连接,调用`redis.quit()`方法å³å¯æ–开连接。需è¦æ³¨æ„的是æ–开连接åŽä¹‹å‰å»ºç«‹çš„连接将ä¸å†å¯ç”¨ï¼Œä¸‹ä¸ªè¯·æ±‚到æ¥æ—¶éœ€è¦ä½¿ç”¨`uniCloud.redis()`方法é‡æ–°å»ºç«‹è¿žæŽ¥ã€‚ + +**如未按照上述说明进行æ“作,redis连接将会一直å 用云函数实例,导致云厂商æŒç»è®¡ç®—云函数执行时间,å¯èƒ½ä¼šå¯¼è‡´æ¶ˆè€—大é‡äº‘资æºè€Œäº§ç”Ÿé¢å¤–费用** + +**务必确定自己已ç†è§£æ¤æ–‡æ¡£å†…å®¹ï¼Œå› æœªæŒ‰ç…§æ–‡æ¡£è¯´æ˜Žä½¿ç”¨å¯¼è‡´çš„é¢å¤–计费DCloudä¸æ‰¿æ‹…任何责任** + +### 注æ„事项 + +- æ’件作者在å‘布æ’件时,如果云函数有特殊设置,应该放入package.jsonä¸ï¼Œç„¶åŽå‘布到æ’ä»¶å¸‚åœºã€‚è¿™æ ·å°±ä¸ç”¨å†é€šè¿‡è¯´æ˜Žæ–‡æ¡£ä¸€æ¥ä¸€æ¥å¼•å¯¼ç”¨æˆ·åŽ»é…置云函数定时触å‘器ã€å†…å˜ã€urlåŒ–è·¯å¾„ç‰ +- 在web控制å°ä¿®æ”¹äº‘函数é…ç½®åŽï¼Œé€šè¿‡HBuilderX的下载云函数èœå•ä¼šåœ¨package.jsonå†…æ·»åŠ ä¿®æ”¹åŽçš„云函数é…ç½® +- ä¸Šä¼ äº‘å‡½æ•°æ—¶ï¼Œå¦‚æžœé¡¹ç›®ä¸‹çš„package.json内包å«äº‘函数é…置会åŒæ—¶è¿›è¡Œäº‘函数的é…置更新 +- package.jsonåªæœ‰äº‘端部署æ‰ç”Ÿæ•ˆï¼Œæœ¬åœ°è¿è¡Œä¸ç”Ÿæ•ˆã€‚ +- cloudfunction-configä¸å¯åˆ 除云端é…置。例:云端已é…ç½®triggers(定时触å‘å™¨ï¼‰ï¼Œåˆ é™¤cloudfunction-config内的triggerä¸ä¼šåˆ 掉云端的定时触å‘器 +- runtimeå‚数(nodejs版本)仅å¯åœ¨åˆ›å»ºäº‘函数时生效,ä¸å¯ä¿®æ”¹ + + +### 云函数的数é‡ã€ä½“积ã€å†·å¯åŠ¨çš„平衡 + +鉴于: +- æ¯ä¸ªæœåŠ¡ç©ºé—´çš„云函数数é‡æ˜¯æœ‰é™çš„,阿里云是48个,腾讯云是9~149个,[详è§](price.md) +- æ¯ä¸ªäº‘函数的体积é™åˆ¶æ˜¯10M(å«node_modules) +- 云函数有冷å¯åŠ¨é—®é¢˜ + +基于以上情况,对开å‘模å¼æœ‰å¦‚下建议: + +1. 一般ä¸å»ºè®®ä½¿ç”¨ä½“积较大ã€ä¾èµ–较深的node_modules。多使用DCloud官方或æ’件市场æ供的库。 +2. 优先使用clientDB,ä¸å 用云函数数é‡ï¼Œä¹Ÿä¸ç”¨ç¼–写æœåŠ¡å™¨ä»£ç 。 +3. 对云对象或云函数åšé€‚当的åˆå¹¶å’Œæ‹†è§£ã€‚ + - 低频且对用户体验影å“较大的æ“作ä¸å»ºè®®ç‹¬ç«‹ä½¿ç”¨äº‘函数,åˆå¹¶åˆ°é«˜é¢‘云函数ä¸ã€‚ + - 控制好å•ä¸ªäº‘函数体积,有的开å‘者喜欢使用[å•è·¯ç”±äº‘函数](https://ext.dcloud.net.cn/search?q=%E8%B7%AF%E7%94%B1&orderBy=WeekDownload&cat1=7),整个æœåŠ¡ç©ºé—´å°±ä¸€ä¸ªäº‘å‡½æ•°ã€‚è¿™ä¹Ÿå¾—æ ¹æ®å®žé™…情况,如果云函数体积超过6M也还是建议分拆。 + - 用户体系方é¢ï¼Œå®˜æ–¹å·²ç»æä¾›uni-id-co云对象,å†æé…clientDB,常规业务就够了。有特殊需求å¯ä»¥å†é€‚度补若干云对象。ä¸å¤ªä¼šå‘生云函数数é‡ä¸è¶³çš„情况。 +4. å¿…è¦æ—¶å¯ä»¥ä½¿ç”¨å¤šä¸ªæœåŠ¡ç©ºé—´ï¼Œè·¨æœåŠ¡ç©ºé—´ä½¿ç”¨ + +## cloudfunctions_init(已废弃) + +`HBuilderX 2.9`版本,`uniCloud`æ供了`cloudfunctions_init.json`æ¥æ–¹ä¾¿å¼€å‘者快速进行云函数的åˆå§‹åŒ–æ“作。 + +**注æ„:HBuilderX 3.0.0版本起ä¸å†ä½¿ç”¨cloudfunctions_init.jsonæ¥åˆå§‹åŒ–云函数。改为使用在云函数目录下通过package.json进行é…置,具体è§ä¸Šä¸ªç« 节** + +详细调整如下: + +ä¸å†ä½¿ç”¨cloudfunctions_init.json,内容被分散到æ¯ä¸ªäº‘函数的package.jsonçš„`cloudfunction-config`å—段下 + +package.jsonæ˜¯ä¸€ä¸ªæ ‡å‡†json文件,ä¸å¯å¸¦æ³¨é‡Šã€‚下é¢æ˜¯ä¸€ä¸ªpackage.json示例 + +```json +{ + "name": "add-article", + "version": "1.0.0", + "description": "æ–°å¢žæ–‡ç« ", + "main": "index.js", + "dependencies": { + + }, + "cloudfunction-config": { + "memorySize": 256, + "timeout": 5, + "triggers": [{ + "name": "myTrigger", + "type": "timer", + "config": "0 0 2 1 * * *" + }], + "path": "" + } +} +``` + +cloudfunction-config说明如下 + +```js +{ + "memorySize": 256, // 函数的最大å¯ç”¨å†…å˜ï¼Œå•ä½MB,å¯é€‰å€¼ï¼š 128|256|512|1024|2048,默认值256 + "timeout": 5, // 函数的超时时间,å•ä½ç§’,默认值5。最长为60秒,阿里云在定时触å‘时最长å¯ä»¥æ˜¯600秒 + // triggers å—段是触å‘器数组,目å‰ä»…支æŒä¸€ä¸ªè§¦å‘器,å³æ•°ç»„åªèƒ½å¡«å†™ä¸€ä¸ªï¼Œä¸å¯æ·»åŠ 多个 + "triggers": [{ + // name: 触å‘器的åå—,规则è§https://uniapp.dcloud.net.cn/uniCloud/trigger,nameä¸å¯¹é˜¿é‡Œäº‘生效 + "name": "myTrigger", + // type: 触å‘器类型,目å‰ä»…æ”¯æŒ timer (å³ å®šæ—¶è§¦å‘器),typeä¸å¯¹é˜¿é‡Œäº‘生效 + "type": "timer", + // config: 触å‘器é…置,在定时触å‘器下,config æ ¼å¼ä¸º cron 表达å¼ï¼Œè§„则è§https://uniapp.dcloud.net.cn/uniCloud/trigger。使用阿里云时会自动忽略最åŽä¸€ä½ï¼Œå³ä»£è¡¨å¹´ä»½çš„一ä½åœ¨é˜¿é‡Œäº‘ä¸ç”Ÿæ•ˆ + "config": "0 0 2 1 * * *" + }], + // 云函数Url化path部分,阿里云需è¦ä»¥/http/开头 + "path": "" +} +``` + +**HBuilderX 3.0.0之å‰ç‰ˆæœ¬ï¼Œè¯·ç»§ç»é˜…读下é¢æ–‡æ¡£** + +**使用方å¼** +- 在`cloudfucntions`目录å³é”®å³å¯åˆ›å»º`cloudfunctions_init.json`, +- 编写好json内容,在`cloudfunctions_init.json`上å³é”®åˆå§‹åŒ–云函数é…置。 + +**cloudfunctions_init.jsonå½¢å¼å¦‚下** + +```json +{ + "fun-name": { // 云函数å称 + "memorySize": 256, // 函数的最大å¯ç”¨å†…å˜ï¼Œå•ä½MB,å¯é€‰å€¼ï¼š 128|256|512|1024|2048,默认值256 + "timeout": 5, // 函数的超时时间,å•ä½ç§’,默认值5。 + // triggers å—段是触å‘器数组,目å‰ä»…支æŒä¸€ä¸ªè§¦å‘器,å³æ•°ç»„åªèƒ½å¡«å†™ä¸€ä¸ªï¼Œä¸å¯æ·»åŠ 多个 + "triggers": [{ + // name: 触å‘器的åå—,规则è§https://uniapp.dcloud.net.cn/uniCloud/trigger,nameä¸å¯¹é˜¿é‡Œäº‘生效 + "name": "myTrigger", + // type: 触å‘器类型,目å‰ä»…æ”¯æŒ timer (å³ å®šæ—¶è§¦å‘器),typeä¸å¯¹é˜¿é‡Œäº‘生效 + "type": "timer", + // config: 触å‘器é…置,在定时触å‘器下,config æ ¼å¼ä¸º cron 表达å¼ï¼Œè§„则è§https://uniapp.dcloud.net.cn/uniCloud/trigger。使用阿里云时会自动忽略最åŽä¸€ä½ï¼Œå³ä»£è¡¨å¹´ä»½çš„一ä½åœ¨é˜¿é‡Œäº‘ä¸ç”Ÿæ•ˆ + "config": "0 0 2 1 * * *" + }], + // 云函数Url化path部分,阿里云需è¦ä»¥/http/开头 + "path": "" + } +} + +```