# enjoy-plus-91 **Repository Path**: ifercarly/enjoy-plus-91 ## Basic Information - **Project Name**: enjoy-plus-91 - **Description**: 享家小程序~~~~~~~~~~~ - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-06-28 - **Last Updated**: 2023-08-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 01. 实时通信(预约、聊天、动态图表...)? HTTP 协议特点:基于请求响应的(必须要前端主动发起才能拿到消息/数据)。 轮询:前台开定时器每隔一段时间向后端发请求。 WebSocket:全双工通信协议(能做到服务端主动的往前端推消息),主流的包 `Socket.IO`。 ## 02. `setTimeout(function() { 这里一定是 1s 准时打印吗 }, 1000)`? ```js setTimeout(function() { console.log(1) }, 1000) // 取决于执行栈中同步代码执行时间有没有超过 1s while(true) {} ``` 一定是 1s 准时打印吗? 为什么? 怎么解决(怎么保证就是 1s)? ```js web worker // 可以开启多线程,例如我可以把耗时较多的任务放到 web worker 开启的线程中执行 ``` ## 03. 事件循环 / Event Loop / JS 的执行机制? 1\. JS 代码的执行分为同步代码和异步代码; 2\. 当碰到同步代码时,直接在执行栈中执行; 3\. 当碰到异步代码并且时机成熟时(例如定时器的时间到了),就把异步代码添加到任务队列中; 4\. **当执行栈中的同步代码执行完毕后**; 5\. 就去任务队列中把异步代码拿到执行栈中执行,这种反复去任务队列中拿异步代码并放到执行栈中执行的操作就是事件循环。 ## 04. refreshToken token 有效期不能太短,太短的话影响用户体验;token 有效期也不能太长,太长的话安全性不好。 出于安全性的考虑,token 的有效期一般不会很长,例如 2 个小时,已经照顾到了安全性,所以接下来该如何照顾到用户体验的问题呢? refreshToken 是啥? 答:是登录成功后,后端返回的一个字符串,一般是和 token 一起返回的。 他是干啥的? 答:当 token 过期后,refreshToken 是用来换取新的 token 的。 有效期是多久? 答:refreshToken 的有效期一般很长,例如半个月。 那么 refreshToken 有效期设置的那么长怎么就不担心安全性问题了? 答:因为 refreshToken 仅仅是 token 过期的一刹那带那么一次,没有 token 那么频发,从概率上来说不容易被抓取到。 1\. 用户登录成功后,存储 refresh_token。 `miniprogram\pages\login\index.js` ```js app.setToken(data.token, data.refreshToken) ``` 2\. 在响应拦截器判断 401,调用刷新 token 的接口。 `miniprogram\utils\http.js` ```js http.intercept.response = async ({ statusCode, data }) => { if (statusCode === 401) { const { data } = await wx.http({ url: '/refreshToken', method: 'POST', header: { Authorization: app.refresh_token } }) } // 数据的脱壳 return data } ``` 注意上面用到了 app.refresh_token,意味着在小程序启动的时候,要从本地获取一下挂载到 app。 `miniprogram\app.js` ```js App({ onLaunch() { // ... this.getToken('refresh_token') }, // ... }) ``` 3\. 设置到本地和 app 中。 ```js http.intercept.response = async ({ statusCode, data }) => { if (statusCode === 401) { // ... app.setToken(data.token, data.refreshToken) } // 数据的脱壳 return data } ``` 4\. 获取 refresh_token 的时候有可能也会 401,死循环。 ```js http.intercept.response = async ({ statusCode, data, config }) => { if (statusCode === 401) { if (config.url.includes('/refreshToken')) { // 这一次的 401 是由于调用刷新 token 的接口的时候,refreshToken 过期导致的 const currentPages = getCurrentPages() const currentPage = currentPages[currentPages.length - 1] // currentPage.route 页面地址 return wx.redirectTo({ url: `/pages/login/index?redirectUrl=/${currentPage.route}`, }) } // ... } // 数据的脱壳 return data } ``` 5\. 把错误的请求(401)重新发送。 ```js http.intercept.response = async ({ statusCode, data, config }) => { if (statusCode === 401) { // ... // 根据最新的 token,把这一次错误的请求信息重新再发一次 const allConfig = Object.assign({}, config, { header: { Authorization: 'Bearer ' + data.token } }) return wx.http(allConfig) } // 数据的脱壳 return data } ``` ## 05. 微信里面如何上传文件? ```js wx.uploadFile({ url: wx.http.baseURL + '/upload', filePath: avatarUrl, header: { Authorization: app.token }, name: 'file', // 后端会通过 file 获取文件信息,看接口文档 // 除了文件信息,其他参数一律写到 formData 中 formData: { type: 'avatar' }, success: (res) => { const resResult = JSON.parse(res.data) this.setData({ 'userInfo.avatar': resResult.data.url }) } }) ``` ## 06. 位置相关的几个 API? 获取当前位置的经纬度:`wx.getLocation()` 根据选择位置获取经纬度:`wx.chooseLocation()` 获取经纬度 => 地址逆解析(腾讯地图 QQMap.reverseGeocoder)=> 根据经纬度搜索周边(QQMap.search)... ## 07. 小程序上传图片? 通过 `wx.chooseMedia()` 拍照或选择照片,拿到`临时路径`,通过 `wx.uploadFile()`,可以根据临时路径找到文件信息再传到后端。 ## 08. Vant Weapp 中常用的几个组件? [van-action-sheet](https://vant-contrib.gitee.io/vant-weapp/#/action-sheet)、[van-datetime-picker](https://vant-contrib.gitee.io/vant-weapp/#/datetime-picker)、[van-popup](https://vant-contrib.gitee.io/vant-weapp/#/popup)、van-uploader ## 09. 重点放在整个项目的业务逻辑?