你的一句承诺,就能避免很多错

简介: 你的一句承诺,就能避免很多错

title: 你的一句承诺,就能避免很多错
date: 2020-05-11 16:08:00.0
updated: 2020-05-14 10:31:27.0
url: https://www.ufec.cn/archives/promise.html
thumbnail: https://ghproxy.com/https://raw.githubusercontent.com/ufec/picGoImg/main/blog/2020/05/promise-35e88f499c384a2e9d777abbb48864e3.webp
categories:

  • 代码

tags:

  • NodeJs
  • Promise

Promise 简介

它允许您将处理程序与异步操作的最终成功值或失败原因相关联。这使异步方法可以像同步方法一样返回值:异步方法返回立即提供最终值的承诺,而不是立即返回最终值。

为什么用 Promise

因为 JavaScript 是单线程的,一些 I/O 操作,如网络请求,读写文件等等会使得进程阻塞,使人看起来是无响应状态,但异步操作可以弥补,可是异步操作在某些场景会使得我们得到的结果“不一致”,例如:

const fs = require('fs');
fs.readFile('./cookie/bilibili.txt', (err, data)=>{
    if (err) throw "error";
    console.log(data);
});

console.log("假如此处是需要等待读取文件完成后才要执行的操作");

结果:

readfile.webp

当然一般读一些必要文件(如 cookie、配置文件)之类的,用同步可能更好,这里只是做异步操作演示,这使得我们的代码看起来好像不是按照“顺序结构”执行,直接这么用,就会出问题。
异步不会马上返回结果,他会在将来的某个时刻执行完毕后才返回结果,如果按照顺序结构来实现逻辑,必然会出现问题,
在许多时候我们需要嵌套来解决问题,当使用异步回调来嵌套时,一不小心就会踏入回调地狱,使得代码看起来臃肿,难以维护

用 Pormise 来解决有什么好处

  • promise 是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外)
  • 代码易读,便于维护
  • 多个异步等待合并便于解决
  • 并未剥夺函数 return 的能力,因此无需层层传递 callback,进行回调获取数据,无论成功与否,都会将结果与状态联系起来

Promise 三大状态

  1. 初始状态(pending)
  2. 成功状态(fulfilled)
  3. 失败状态(rejected)

只能由初始变为成功或失败状态,状态一经改变不会再变,Promise 是一个构造函数,自身有 all、reject、resolve 等方法,原型上有 then、catch 等方法。
resolve:作为 Promise 的两个参数之一,与异步操作成功相关联,并将成功结果作为参数返回
reject:作为 Promise 的两个参数之一,与异步操作失败相关联,并将失败结果作为参数返回
resolveandreject.webp
all:方法执行后返回的依旧是 promise,可以并行多个异步操作,都成功就返回成功,并且在一个回调中处理所有的返回数据。返回的数据与传的参数数组的顺序是一样的。

function read(content) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve(content)
        }, 1000)
    })
}

let result = Promise.all([read(1), read(2)]);
result.then((data) => {
    console.log(data) //[ 1, 2 ]
})

then 用于捕获状态的改变,当有多个 then 的时候,如果 then 中返回了一个 promise 会将 promise 的结果继续传给第二 then 中(如果结果是将状态改成成功就走下一个 then 的成功回调,状态改为失败就走下一个 then 的失败回调)
这个部分可参照简书作者新叶子的文章Promise 的基本用法(一),我就不一一搬过来了

catch 用于捕捉异常,当然单个的情况,也可以将异步操作失败的结果,作为参数放到 catch 中,与放到 then 的第二个参数基本一致,当有多个的时候,catch 用于公共的 error

实例场景

这是我自己写一个接口时遇到的场景。
需求:
首先手动获取 cookie,存入文件,当用户访问我的接口时,读取并携带 cookie,对用户传参进行处理请求第三方接口,获取数据。此处 cookie 有效期为两小时,需要服务端在请求第三方接口获取数据时,如果检测到 cookie 过期,去请求 refresh 接口刷新 cookie,先用刷新的 cookie 去请求第三方接口返回成功数据给用户后,在更新本地 cookie 文件,
这其中涉及了两次异步网络请求、一次异步写文件操作,第一次写的时候,没想那么多,直接多次回调,后来便出现了问题,异步网络请求还未完成,代码已经执行到了结尾,重启进程才能继续使用,

初步解决方案:
请求第三方接口作为单独一个 main 函数,刷新 token 作为单独 refresh_token 函数,只需要在检测到 cookie 过期时调用 refresh_token 这个函数,成功后回调 main 函数,后来发现跟初始方案差不多,依然会出问题,想到了当初写领券小程序时候用到的 Promise 解决生成淘口令并提示用户的问题。

最终解决方案:
main 函数和 refresh_token 函数均返回一个 Promise,将成功和失败逻辑处理好,这样一来,在最后返回结果处就一定能保证返回正确结果(这里是第三方接口未失效、网络等一切正常),至于写文件操作依然用异步,这样能以最快的速度将结果返回给用户,而写文件操作继续执行中

个人愚见,部分来源于网上资料,如有错误请指正!!!

目录
相关文章
|
3月前
|
消息中间件 前端开发 NoSQL
试用期被裁是有补偿的!一定要记得领取~
试用期被裁是有补偿的!一定要记得领取~
62 6
试用期被裁是有补偿的!一定要记得领取~
|
8月前
|
安全 测试技术
技术债是我们的错吗?
技术债是我们的错吗?
|
7月前
|
安全 测试技术
发现和拒绝糟糕的IT咨询建议的8种方法
发现和拒绝糟糕的IT咨询建议的8种方法
|
消息中间件 前端开发 NoSQL
糟糕!试用期被裁了
糟糕!试用期被裁了
95 0
网上平台提现被拒客服以各种理由不给出应该怎么办?
网上被黑可能是你遇到黑平台才会导致的,遇到事情不要慌一下文章可能帮你换回损失
167 1
网上平台提现被拒客服以各种理由不给出应该怎么办?
|
存储 运维 监控
语雀故障与反思,随便再领半年会员!
语雀故障与反思,随便再领半年会员!
394 0
|
小程序 数据库
忘了交这个钱,小心专利失效!
忘了交这个钱,小心专利失效!
252 0
忘了交这个钱,小心专利失效!
|
开发者
阿里云开发者社区标兵奖励办法全新升级
阿里云ACE成员奖励办法升级啦,开发小伙伴们赶紧看过来~~
6944 0
|
监控 安全 测试技术
一个bug引发惨案!成功追回损失后,拼多多还应做什么?
1月20日凌晨,互联网销售平台拼多多遭遇了“优惠券Bug”:网站每一位注册用户可以通过微信渠道、网页端、QQ渠道等,领取面值为100元的优惠券,该优惠券适用该网站的商品,有效期为一年。随后,有网友曝出,用领取的优惠券可以充值话费、Q币。
2915 0