- 关于progress进度条的问题?
我想问下,我现在想实现一个下载文件并显示动态进度条的功能,但看了文档发现percent这个必须要有固定的值(类似80)这样,但进度是一直变化的,该如何让它实现动态进度条呢 [图片]
2019-11-18 - 微信小程序如何引入npm包?
前言 你还在下载源码复制到项目中去使用吗?现在已经不需要了! 从小程序基础库版本 2.2.1 或以上、及开发者工具 1.02.1808300 或以上开始,小程序支持使用 npm 安装第三方包。 接下来我们以npm引用 dayjs 库为案例。 dayjs:一个轻量的处理时间和日期的 JavaScript 库,和 Moment.js 的 API 设计保持完全一样. 如果您曾经用过 Moment.js, 那么您已经知道如何使用 Day.js。 Moment.js 的 2kB 轻量化方案,拥有同样强大的 API [代码] dayjs() .startOf('month') .add(1, 'day') .set('year', 2018) .format('YYYY-MM-DD HH:mm:ss') [代码] 🕒 和 Moment.js 相同的 API 和用法 💪 不可变数据 (Immutable) 🔥 支持链式操作 (Chainable) 🌐 国际化 I18n 📦 仅 2kb 大小的微型库 👫 全浏览器兼容 地址:https://github.com/iamkun/dayjs 引用步骤 打开调试器区域的【终端】面板。 [图片] 输入[代码]npm init[代码],然后填写初始化信息,默认值可以按回车。 填写完成后,会生成一个package.json文件。 [图片] 安装 dayjs:在终端输入 [代码]npm install dayjs --save[代码] 点击开发者工具中的工具栏:详情 --> 本地设置 --> 勾选【使用 npm 模块】 [图片] 点击开发者工具中的菜单栏:工具 --> 构建 npm [图片] 引入使用 [图片] dayjs 详细使用文档:https://day.js.org/zh-CN/
2020-09-30 - 小程序里使用async和await变异步为同步,解决回调地狱问题
最近好多同学,学习完石头哥的云开发基础以后,自己实际项目中,总会遇到各种各样的异步问题。 一,异步问题 所谓异步:就是我们请求数据库的数据时,由于网速等各方面原因,数据返回的时间不确定,而我们要使用这些数据,就要等数据返回成功后才可以使用,否则就会报错。 1-1,问题描述 如下: [图片] 好多同学都会认为代码从上往下执行,会先执行请求成功,然后才会执行第11行的代码,商品个数也应该是2. 但是我们的第11行打印却是0.这是为什么呢。 这个错误的原因就是我们使用数据没有写在请求成功里面。正确数据请求返回是异步的,什么时候请求成功不知道,但是我们的第11行代码不会等我们数据请求成功才会执行,所以第11行的打印是0而不是2. 1-2,解决方案 要想解决上面的问题,把你使用数据的地方写到数据请求成功里。 [图片] 这样就能解决异步的问题,但是如果我们有很多地方要使用请求成功的数据,该怎么办呢,总不能把所有的代码都写在数据请求成功里吧。这个时候就要借助async和await来解决这个问题了。 二,使用async和await变异步为同步 所谓的同步,就是我们保持代码正常的从上往下执行。但是呢只要有数据请求,就会有异步问题。所以我们这里要想办法变异步为同步。这就要用到async和await了。 代码如下: [图片] 可以看出,我们不用把使用到数据的代码写到请求成功里就可以了,这样代码读起来是不是常规的从上往下执行的了。 await翻译过来就是等待的意思,其实这里的意思就是,我们等待数据请求完成后,把数据的返回结果赋值给res,然后等数据请求成功以后,就可以正常使用数据请求返回的结果啦。 注意事项 我们在小程序里使用async和await时,一定是成对的。 async放在函数名前面,await放在数据请求前面。 [图片] 并且也要勾选一下:增强编译 [图片] 现在最新版本的小程序开发者工具好像已经支持async和await方法了,好像不勾选增强编译也没事。但是安全起见,还是勾选下增强编译比较好。 三,回调地狱 比如我们有这么一个需求: 用户注册的时候,要先查询是否注册过,没有注册过,才可以新注册。而注册成功后,才可以查看商品列表。 3-1,问题描述 这里给大家分析下需求 [图片] 如果只看流程图,肯定会觉得很简单;但是里面的链路你要认清一个现实。 就是我们如果想最终把商品显示到页面上,必须依赖每个流程都要请求成功。现在是只有3个请求,如果有100个呢,一层套一层的,最后会把你绕晕。这就是回调地狱。 3-2,回调地狱代码 单纯的给你讲,你可能体会不到回调地狱的坏处。那么我用代码实现下我们上面的需求。 假设我们有 用户表:user 商品表:goods 比如我们要注册一个名为”小石头“的用户 第一步:先查询是否注册过 [图片] 可以看出返回的个数为0,代表没有注册过 第二步:注册用户 [图片] 可以看到我们已经可以注册成功了,但是这个时候代码已经嵌套了。 [图片] 第三步:查询商品 由于我们第二步,已经注册’小石头‘成功,所以我们这一步注册一个’大石头‘,注册成功后查询商品。 首先看下代码,这个时候已经嵌套3层了。代码已经变得有点乱了 [图片] 看下结果 [图片] 可以看出我们已经能够成功的查询到商品数据了。 这里只嵌套了三层,看起来还可以接受,如果再继续一层层的嵌套呢。后面代码会变得越来越乱,为了避免回调地狱,我们也可以使用async和await来改造代码。 四,async结合await解决回调地狱 首先看下改造后的代码 [图片] 可以看到代码简洁了很多,逻辑也就是正常的从上往下执行代码 为了更明显的比较。 [图片] 到这里我们就讲完了,是不是感觉使用async和await让你的代码简洁了很多。赶紧跟着石头哥的这篇文章去体验下吧。
2021-05-29 - JavaScript_Promise的总结
JavaScript-Promise总结 前言: 最近在做项目对接后端接口时,遇到了一个bug,和promise有关,于是在网上找资料,找啊找,发现自己对Promise的了解还是很生疏的,于是就开始了对promise的学习,刚好最近也想开始写一些文章来记录自己的学习路程,也希望可以帮助到大家。然后,就开始了我前端之路的第一篇知识输出文章,请大家多多指教! 正文: Promise概述 异步编程是JavaScript一大特点,建议大家先了解一下JavaScript的异步编程实现,这里推荐一篇文章—JavaScript异步编程 - 熊建刚的文章 - 知乎 https://zhuanlan.zhihu.com/p/26567159 Promise是实现异步编程的一种解决方案,比传统的的解决方案(回调函数和事件)更加先进,先进在哪里呢?上代码! [代码]//传统异步编程方式 setTimeout(function(){ console.log("doThing1"); setTimeout(function(){ console.log("doThing2"); setTimeout(function(){ console.log("doThing3"); setTimeout(function(){ console.log("doThing4"); },1000) },1000) },1000) },1000) //promise实现 let p1=new Promise((resolve,reject)=>{ setTimeout(function () { console.log("doThing1"); resolve(); }, 1000); }) let p2=new Promise((resolve,reject)=>{ setTimeout(function () { console.log("doThing1"); resolve(); }, 1000); })v let p3=new Promise((resolve,reject)=>{ setTimeout(function () { console.log("doThing1"); resolve(); }, 1000); }) let p4=new Promise((resolve,reject)=>{ setTimeout(function () { console.log("doThing1"); resolve(); }, 1000v); }) p1.then(p2).then(p3).then(p4); [代码] 上面的代码,我们想按照顺序去做4件事情,如果按照传统的方式来实现很容易造成“函数瀑布”,这样的代码被称为“回调地狱”,看起来就很头疼,像promise这样实现更为直观,维护起来也方便很多,这仅仅是代码书写上的优势,在一些错误处理,顺序性等等都比传统异步编程更为优化,这里就不做深究了。 “Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息”。一个 Promise对象会将异步操作的最终结果和结果的处理程序关联起来(成功or失败),那么自然就要求promise需要有状态,我们才可以知道promise现在是成功了还是失败了。 Promise的状态: pending(等待),初始状态,未知操作成功还是失败 fulfilled(已完成),最终状态,操作成功,可以调用成功处理程序 rejected(已失败),最终状态,操作失败,可以调用失败处理程序 这里引入一个例子:小明的妈妈在做家务没空买菜,那么她叫小明去买菜,这个任务就是一个promise,好,小明去买菜了,小明买菜这个过程是一个异步操作,那么小明买菜的结果是什么呢?这就是说这个命令有没有完成?有两种情况,第一种是小明成功买到菜了,接下来小明妈妈就是做饭啦,第二种情况,小明把钱拿去打游戏了没买到菜,接下来小明妈妈就是把他打一顿啦… 接下来讲promise的使用都会用到这个例子。 Promise的方法 Promise()-promise的构造函数 作用: 创建一个新的 [代码]Promise[代码] 对象。该构造函数主要用于包装还没有添加 promise 支持的函数。 Promise接受函数两个参数(resolve, reject),当异步任务成功时,调用第一个参数resolve,将promise对象的状态设为fulfilled,并返回成功值;失败时将调用第二个参数reject将promise对象的状态设为rejected,并返回失败原因; 使用: [代码]let order=new Promise((resolve,reject)=>{ setTimeout(()=>{ //小明买菜ing // (1)小明一路破关斩将,抵御各种诱惑,成功买到一条鱼和一斤牛肉 //(2)小明看到菜市场旁边的游戏厅,被里面的游戏所吸引,把钱全花在打游戏那里了,没有买到菜 //小明回到家告诉妈妈 resolve("我买到菜了!买了一条鱼和一斤牛肉") //reject("我没有买到菜,钱全花在打游戏了......") //敢作敢当.... },1000)//这里用setTimeout来模拟小明去买菜这个异步任务 }) [代码] 注意!promise的状态一经决定,无法改变,所以当用了resolve再用reject时reject不起效果,promise状态仍是fulfilled [代码]Promise.prototype.then()[代码] 作用: 这个方法可以获取promise的状态,并进行结果处理。 它最多需要有两个参数:Promise 的成功和失败情况的回调函数。 语法: [代码]promise.then(value => { // fulfillment }, reason => { // rejection }); [代码] 使用: [代码]let order=new Promise((resolve,reject)=>{ setTimeout(()=>{ //小明买菜ing // (1)小明一路破关斩将,抵御各种诱惑,成功买到一条鱼和一斤牛肉 //(2)小明看到菜市场旁边的游戏厅,被里面的游戏所吸引,把钱全花在打游戏那里了,没有买到菜 //小明回到家告诉妈妈 resolve("我买到菜了!买了一条鱼和一斤牛肉") //reject("我没有买到菜,钱全花在打游戏了......") //敢作敢当.... },1000)//这里用setTimeout来模拟小明去买菜这个异步任务 }) order.then((res)=>{ console.log(res); console.log("妈妈夸了一顿小明,并做了红烧鱼和爆炒牛肉"); },(err)=>{ console.log(err); console.log("妈妈打了一顿小明,并决定今晚出去吃"); //好像小明这样做确实不错,可以出去吃了 }) //输出结果: 我买到菜了!买了一条鱼和一斤牛肉 妈妈夸了一顿小明,并做了红烧鱼和爆炒牛肉 //如果是reject("我没有买到菜,钱全花在打游戏了......") 我没有买到菜,钱全花在打游戏了...... 妈妈打了一顿小明,并决定今晚出去吃 [代码] tips: 由于 then 和 [代码]Promise.prototype.catch()[代码]方法的返回值都是 promise,它们可以被链式调用——这同时也是一种被称为复合( composition) 的操作。 [代码]//类似 p1.then(p2).then(p3).then(p4).catch(p5).then(p6)....... [代码] [代码]Promise.prototype.catch()[代码] 作用: 这个方法主要获取promise错误状态,并进行结果处理。其实和[代码]promise.then(undefined,onRejected)[代码]时一样的,不过promise.then优先(等下会有示例)。 语法: [代码]promise.catch(function(reason) { // 拒绝z }); [代码] 使用: [代码]let order=new Promise((resolve,reject)=>{ setTimeout(()=>{ //小明买菜ing // (1)小明一路破关斩将,抵御各种诱惑,成功买到一条鱼和一斤牛肉 //(2)小明看到菜市场旁边的游戏厅,被里面的游戏所吸引,把钱全花在打游戏那里了,没有买到菜 //小明回到家告诉妈妈 // resolve("我买到菜了!买了一条鱼和一斤牛肉") reject("我没有买到菜,钱全花在打游戏了......") //敢作敢当.... },1000)//这里用setTimeout来模拟小明去买菜这个异步任务 }) order.catch(err=>{ console.log("catch err: "+err); console.log("妈妈打了一顿小明,并决定今晚出去吃"); }) //输出结果: catch err: 我没有买到菜,钱全花在打游戏了...... 妈妈打了一顿小明,并决定今晚出去吃 [代码] tips: 当和[代码]promise.then(undefined,onRejected)[代码]同时存在时,onRejected优先 [代码]//构造Promise order同上 order.then(undefined,err=>{ console.log("then err: "+err); }) .catch(err=>{ console.log("catch err: "+err); }) //输出结果: then err: 我没有买到菜,钱全花在打游戏了...... [代码] catch可以捕获then()里面的函数 [代码]order.then(undefined,err=>{ console.log("then err: "+err); throw Error("then出错了") }) .catch(err=>{ console.log("catch err: "+err); }) //输出结果 then err: 我没有买到菜,钱全花在打游戏了...... catch err: Error: then出错了 [代码] 3.当在链式调用时,catch可以捕获前面任意一个then中的错误,这也就是说我们写代码的时候最好可以用上catch [代码]//类似 p1.then(p2).then(p3).then(p4).then(p5).catch(err)....... //catch可以捕获p2 p3 p4 p5中任意一个中的错误 [代码] [代码]Promise.prototype.finally()[代码] 作用: 当promise结束是,无论最终状态如何,fulfilled还是rejected,都会执行指定回调函数 语法: [代码]promise.finally(function() { // 返回状态为(resolved 或 rejected) }); [代码] 使用: [代码]let order=new Promise((resolve,reject)=>{ setTimeout(()=>{ //小明买菜ing // (1)小明一路破关斩将,抵御各种诱惑,成功买到一条鱼和一斤牛肉 //(2)小明看到菜市场旁边的游戏厅,被里面的游戏所吸引,把钱全花在打游戏那里了,没有买到菜 //小明回到家告诉妈妈 // resolve("我买到菜了!买了一条鱼和一斤牛肉") reject("我没有买到菜,钱全花在打游戏了......") //敢作敢当.... //promise的状态一经决定,无法改变,所以当用了resolve再用reject时reject不起效果,promise状态仍是fulfilled },1000)//这里用setTimeout来模拟小明去买菜这个异步任务 }) order.then((res)=>{ console.log(res); console.log("妈妈夸了一顿小明,并做了红烧鱼和爆炒牛肉"); },(err)=>{ console.log(err); console.log("妈妈打了一顿小明,并决定今晚出去吃"); //好像小明这样做确实不错,可以出去吃了 }).catch((err)=>{ //获取前面出现的错误,有可能妈妈做饭的时候鱼被猫吃了....... }).finally(()=>{ console.log("无论结果如何,最终都是要吃饭的!事已至此,先吃饭吧。。。。"); }) //输出结果 我没有买到菜,钱全花在打游戏了...... 妈妈打了一顿小明,并决定今晚出去吃 无论结果如何,最终都是要吃饭的!事已至此,先吃饭吧。。。。 [代码] [代码]Promise.resolve()[代码] 作用: 返回一个带有成功参数的[代码]Promise[代码]对象。注意此时的promise对象已是fulfilled的最终状态。 参数: 如果参数是一个值,将把这个值作为返回的promise的成功参数 如果这个值是一个 promise ,那么将返回这个 promise 如果是一个thenable,返回的promise会“跟随”这个thenable的对象,采用它的最终状态。 [代码]thenable:[代码] [代码]thenable[代码]是任何含有then()方法的对象或函数,作用使promise的实现更具有通用性 类似: [代码]let thenable = { then: (resolve, reject) => { resolve(thenable) } } [代码] 判断一个对象是不是thenable,用到类型检查,也称为鸭式辩型 [代码]if(p!=null&&(typeof p==="object"||typeof p==="function")&&(typeof p.then==="function")){ //p是一个thenable }else{ //p不是一个thenable } [代码] 示例: [代码]let thenable = { then: (resolve, reject) => { resolve("thenble最终状态") } } let promise=Promise.resolve(thenable) promise.then((res)=>{ console.log(res) },err=>{ //用不上 } ) //打印结果 //thenble最终状态 let promise1 = Promise.resolve(11111); let promise=Promise.resolve(promise1) promise.then((res)=>{ console.log(res) },err=>{ //用不上 } ) //打印结果 //11111 let promise=Promise.resolve(2222) promise.then((res)=>{ console.log(res) },err=>{ //用不上 } ) //打印结果 //22222 [代码] [代码]Promise.reject()[代码] 作用: 返回一个带有拒绝原因的[代码]Promise[代码]对象。注意此时的promise对象已是rejected的最终状态 和[代码]Promise.resolve()[代码]的区别 [代码]Promise.reject[代码] 方法的参数,会原封不动地作为 reject 的参数,变成后续方法的参数。这一点与 [代码]Promise.resolve[代码] 方法不一致。 [代码] //Promise.resolve() 和Promise.reject()的区别 const thenable ={ then(resolve, reject){ // resolve("成功了") reject('出错了'); } }; //Promise.resolve() 和Promise.reject()的区别 //Promise.resolve(thenable) Promise.reject(thenable) .then(res=>{ console.log("then res: "+res) console.log(res===thenable) }) .catch(err =>{ console.log("catch err: "+err) console.log(err===thenable) }) //打印结果 catch err: [object Object] true //当执行Promise.resolve(thenable) catch err: 出错了 false [代码] 对resolve(thenable)结果解析: 当thnable传入resolve时,将立即执行thnable的then方法,resolve返回它的最终状态reject(‘出错了’),此时resolve返回的promise参数并不是一个thnable了,而是“出错了” 而当thnable传入rejected时,并不会执行thnable的then方,而是原封不动将thnable作为resolve返回的promise参数 [代码]Promise.all()[代码] 作用: 整合多个promise示例,返回最终一个promise实例 参数: 一个promise的[代码]iterable[代码]类**(注:Array,Map,Set都属于ES6的iterable类型)** 返回值: Promise的resolve回调执行是在所有输入的promise的resolve回调都结束,或者输入的iterable里没有promise了的时候 只要任何一个输入的promise的reject回调执行或者输入不合法的promise就会立即抛出错误,并且reject的是第一个抛出的错误信息。 个人觉得有点像与操作了,当所有promise都fulfilled时,返回的promise才是fulfilled,完成状态的结果都是一个数组,它包含所有的传入迭代参数对象的值(也包括非 [代码]promise[代码] 值);而当任意一个promise失败时,返回的promise时rejected,Promise.all()异步地将失败的那个结果给失败状态的回调函数,而不管其它 [代码]promise[代码] 是否完成。 [代码]let promise1=Promise.resolve("小明成功买到菜了"); let promise2=Promise.reject("小明没晾衣服"); let promise3=Promise.resolve("小明刷完高数了"); Promise.all([promise1, promise2, promise3]).then(res => { console.log(res); }); //打印结果 [ '小明成功买到菜了', '小明晾衣服了', '小明刷完高数了' ] let promise1=Promise.resolve("小明成功买到菜了"); let promise2=Promise.reject("小明没晾衣服"); let promise3=Promise.resolve("小明刷完高数了"); let promise=Promise.all([promise1, promise2, promise3]); setTimeout(()=>{ console.log(promise) },0) //打印结果 Promise { <rejected> '小明没晾衣服' } [代码] 至于第二个例子我为什么要用setTimeout,大家可以保留疑问,假如直接打印,结果会是[代码]Promise { <pending> }[代码],这就涉及到Promise的异步处理,文章后我会讲解 [代码]Promise.allSettled()[代码] 作用: 方法返回一个在所有给定的promise都已经[代码]fulfilled[代码]或[代码]rejected[代码]后的promise,并带有一个对象数组,每个对象表示对应的promise结果。 如果有多个彼此不依赖的异步任务完成时,然后你要知道所有promise的结果,又不想一个一个地获取时,可以用到这个。相反,假如你的异步任务有依赖则要用Promise.all() 参数: 和[代码]Promise.all()[代码]一致 示例: [代码]let promise1=Promise.resolve("小明成功买到菜了"); let promise2=Promise.reject("小明没晾衣服"); let promise3=Promise.resolve("小明刷完高数了"); Promise.allSettled([promise1, promise2, promise3]).then((result)=>{ result.forEach((item)=>{ console.log(item) }) }) //打印结果 [ { status: 'fulfilled', value: '小明成功买到菜了' }, { status: 'rejected', reason: '小明没晾衣服' }, { status: 'fulfilled', value: '小明刷完高数了' } ] [代码] [代码]Promise.race()[代码] 作用: 返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。 race-比赛,看哪个promise最先被定义最终状态,则返回该结果 参数: 和[代码]Promise.all()[代码]一致 示例: [代码]const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, '小明做完作业了'); //小明做完作业花费了500ms }); const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 100, '小东做完作业了'); //小东做完作业花费了100ms }); let promise=Promise.race([promise1, promise2]); setTimeout(()=>{ console.log(promise) },1000); //打印结果 Promise { '小东做完作业了' } const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, '小明做完作业了'); //小明做完作业花费了500ms }); const promise2 = new Promise((resolve, reject) => { setTimeout(reject, 100, '小东不想作业了'); //小东100ms后就说不做作业了... }); let promise=Promise.race([promise1, promise2]); setTimeout(()=>{ console.log(promise) },1000); //打印结果 Promise { <rejected> '小东不想作业了' } [代码] [代码]Promise.any()[代码] 作用: 与[代码]Promise.all()[代码]相反,及相当于做或操作,只要有一个promise成功了,那么最终结果就成功(只返回第一个成功的promise),如果都不成功,最终promise才为rejected。 参数: 和[代码]Promise.all()[代码]一致 示例: [代码]let promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, '小明做完作业了'); //小明做完作业花费了500ms }); let promise2 = new Promise((resolve, reject) => { setTimeout(reject, 100, '小东不想作业了'); //小东100ms后就说不做作业了... }); let promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 100, '小李做完作业了'); //小明做完作业花费了500ms }); Promise.any([promise1, promise2,promise3]).then(res=>{ console.log(res) }) //打印结果 "小李做完作业了" let promise1 = new Promise((resolve, reject) => { setTimeout(reject, 500, '小明不想作业了'); //小明500ms后就说不做作业了... }); let promise2 = new Promise((resolve, reject) => { setTimeout(reject, 100, '小东不想作业了'); //小东100ms后就说不做作业了... }); let promise3 = new Promise((resolve, reject) => { setTimeout(reject, 200, '小李不想作业了'); //小明100ms后就说不做作业了... }); Promise.any([promise1, promise2,promise3]).catch(err=>{ console.log(err.message)}) //打印结果 "All promises were rejected" [代码] Promise的异步执行 我们先来看一段代码! [代码]let promise1 = Promise.resolve(11111); let promise2 = promise1.then(value => { console.log("promise1的value: " + value); return value; }); console.log(promise2); setTimeout(() => { console.log(promise2); }); //打印结果: Promise { <pending> } promise1的value: 11111 Promise { 11111 } [代码] 是不是和你的预期不一样,这就是Promise的异步执行; 我们来分析一下: 其实代码执行到 [代码]let promise1 = Promise.resolve(11111);[代码] [代码]Promise.resolve[代码]不会在时不会立即执行的,这是交给异步来完成的,那么就顺着执行下面的代码了. 到[代码]let promise2 = promise1.then[代码]时,此时的promise1的状态还是pending,所以promise2也是pending,此时value是undefined的。 然后就是执行[代码]console.log(promise2)[代码],所以打印的第一个是[代码]Promise { <pending> }[代码],之后再[代码]setTimeout[代码],此时promise1 promise2才是操作完成的,value是111。 这也是和JavaScript的异步编程有关! Promise的缺点 一旦新建Promise,它就会立即执行,无法中途取消。 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。 当处于 [代码]pending[代码] 状态时,无法得知目前进展到哪一个阶段(刚开始还是即将完成)。 总结 终于写完了,自己也系统地学完了Promise,输出亦是一种学习的过程。 这篇文章主要是对Promise的理解和使用,至于Promise的实现,我也只是简单的看了大概,大家有兴趣可以继续深究源码。 此文章只代表个人见解,站在巨人的肩膀上看问题,感谢前辈们的贡献,如有错误,请指出!感谢大家!
2021-11-14 - 小程序用户信息相关接口调整公告
为进一步规范开发者调用用户信息相关接口或功能,提升用户体验,平台将对部分用户信息相关功能及接口进行调整,具体如下: 访问蓝牙、添加通讯录联系人、添加日历事件需要用户授权小程序处理用户的个人信息,需要获取用户明示同意,平台计划从2022年2月21日24时起对以下接口增加用户授权: 访问蓝牙:调用wx.openBluetoothAdapter、wx.createBLEPeripheralServer,需要授权scope.bluetooth添加通讯录联系人:调用wx.addPhoneContact,需要授权scope.addPhoneContact添加日历事件:调用wx.addPhoneRepeatCalendar、wx.addPhoneCalendar,需要授权scope.addPhoneCalendar开发者可在平台调整前提前增加使用 wx.getSetting 获取用户当前的授权状态的逻辑,若授权状态为false可以调用 wx.openSetting 打开设置界面,引导用户开启授权。 授权功能详细说明可参考:官方文档 <open-data>组件功能调整开发者在未获取用户明示同意的情况下通过 <open-data>组件 在小程序中展示用户个人信息,用户容易误以为自己的个人信息在未授权的情况下,被小程序获取。平台计划从2022年2月21日24时起回收通过<open-data>展示个人信息的能力,若小程序需收集用户昵称头像等信息,可以通过 头像昵称填写功能 功能进行收集。具体回收方式为: 头像展示 灰色头像用户昵称展示“微信用户”用户性别、地区、语言展示为为空(“”)小程序通过<open-data>展示群名称能力保留,平台会针对小程序生命周期内首次调用该组件展示群名称向用户提示:“群名称仅你可见,小程序无法获取。” 获取手机号能力安全升级此前小程序获取用户手机号是通过基础库接口直接获取encryptedData后进行解密。从基础库2.21.2版本起,回调参数中增加code参数,开发者获取code参数后,通过服务端auth.getPhoneNumber接口,使用code换取encryptedData,用于解密手机号。 为不影响开发者现有逻辑,原有基础库接口中的encryptedData参数依旧保留,建议开发者尽快使用新的方式获取用户手机号。 详细功能描述可参考 官方文档 微信团队 2021年12月27日
2023-09-26