likes
comments
collection
share

Promise/ fetch / async await 我终于学会啦 ...

作者站长头像
站长
· 阅读数 44

爷爷,你关注的作者更新啦!

上周五的某个timing:

【突然发现】某个功能没有实现 -- 【噢原来是】js没有执行 -- 【认真debug】js异步没执行完 -- 【改bug】花了不少时间 -- 【继续深究下去】终于搞明白Promise、async/await和fetch,3个东东之间的关系

好记性不如烂笔头,以下展开1000000000

Promise

MDN文档指路:

  1. Promise
  2. 使用Promise

Overview

  • PromiseJavaScript 中实现异步执行的方式之一

    英文中表示“承诺”,意味着在未来会返回执行结果

  • Promise 是一个对象,有3种状态:

    pending     - 未完成(执行中)
    fulfilled   - 成功
    rejected    - 失败

pending是初始状态,之后变成fulfilled或rejected状态,而且状态不会逆转、不会更改。

类似于煮米饭,生米(pending)只会变熟(fulfilled),或者不熟(rejected)

不熟的米饭不可能变熟 // 除非重新煮(再次使用Promise)

怎么用

  • 通过 new Promise( function(){} )

  • 必须传入一个函数作为参数,函数有两个参数 resolve reject

    • resolve( 返回值 ) - 函数成功时使用
    • reject( 返回值 ) - 函数失败时调用

    返回值可有可无,没有就返回undefined

    成功还是失败,当然是programmer自由发挥,想怎样都不会犯法kkk

只能通过 resolvereject 函数来返回(改变Promise的状态),不能return

  • new的同时,会立即执行这个函数

试水,比如定义一个随机小数,比5大就返回success,否则返回error

let JoyTT = new Promise(function (resolve, reject) {
  let num = Math.random() * 10
  if (num > 5) {
    resolve('success')
  } else reject('error')
}) 

其实可以看出,resolve和reject也是函数,括号内第一个参数会作为返回值,后续可以通过.then() / .catch() 获取返回值

方法(prototype)

.then()

完整写法:Promise对象.then(function result(){},function error(){})

  • 用于接收Promise成功执行的结果(resolve(返回值)
  • function error(){} - Promise失败执行时触发,非必要,一般推荐直接用.catch()方法捕捉错误
  • 返回值:Promise对象

so,then() 方法后可以继续用then()获取上一层then()的返回值

which is 链式调用

.catch()

完整写法:Promise对象.catch(function error(){})

  • 用于捕捉错误

链式调用时,如果过程中任意then()发生错误,就会直接跳到这里被捕捉

.finally()

完整写法:Promise对象.finally(function(){})

  • 无论失败与否都会执行,通常用于执行清理操作或收尾工作

链式调用

多个then()+[catch()] +[finally()]

JoyTT() 
.then(result => { 
    // 第一个异步操作成功后的处理 
    return anotherAsyncFunction(result); 
},
error=>{}) 
.then(result => { 
    // 第二个异步操作成功后的处理 
    return yetAnotherAsyncFunction(anotherResult); 
},
error=>{})
.catch(error => { 
    // 处理任何异常情况 
    console.error("发生错误:", error); 
}) 
.finally(() => { 
    // 执行清理操作 
    console.log("清理操作完成"); 
});

静态方法(其他)

详细文档

  1. Promise.all()
  2. Promise.race()
  3. Promise.any()
  4. Promise.allSettled()

fetch

MDN文档指路: Fetch API

Overview

  • 基于Promise,用于发送网络请求

  • 返回值:Promise对象

    对返回值使用.json()方法,将body解析为可以直接使用的json格式

prototype里还有别的api可以使用

注意:和Promise的原型是不一样的

  • .then() .catch()接收执行结果 捕捉错误

try-catch一样,实现同样的功能

语法

写法:fetch(url,{请求参数})

  • 默认发送get请求,发送其他类型请求必须配置请求参数

比如,post请求

{
    method:"post",
    body:JSON.stringify({ name: "data" }),
    headers:{
    "Content-Type":"application/json"
    }
}

怎么用

因为文档讲解的很好,所以here省略200字 使用Fetch

async await

MDN文档指路: async function

Overview

  • async/await是Promise的语法糖,优化了then()链式调用的问题

async - 将普通函数标记为异步函数

  • 返回值:promise对象

  • 在内部使用return语句 返回的值,需要用then()方法接收

    Promise/ fetch / async await 我终于学会啦 ...

await - 等待异步操作执行完毕,阻塞进程

  • 在async函数内部使用
  • 对同步操作不起效

语法

其实就是在 函数前面 加个async标志

  • async function f () { }

  • async ( () => { } )

怎么用

打个比方,在map方法的回调函数中使用async/await:遍历每一个数组项时,发fetch请求获取 xx 网址的数据

var array = [{role:'Sr. PM'},{role:'Ass. BA'},{role:'Tech Lead'},{role:'QA'}]
array.map(async (role, index) => {
        fetchXml = `?fetchXml=
        <fetch xmlns:generator="MarkMpn.SQL4CDS" aggregate="true">
          <entity name="joy_costtrackingtask">
            <attribute name="joy_pe" alias="PE" aggregate="sum" />
            <attribute name="joy_pc" alias="PC" aggregate="sum" />
            <attribute name="joy_ae" alias="AE" aggregate="sum" />
            <attribute name="joy_ac" alias="AC" aggregate="sum" />
            <filter>
              <condition attribute="joy_costtracking" operator="eq" value="0000-0000" />
            </filter>
          </entity>
        </fetch>`;
        await fetch("https://example.com/joy_costtracking" +fetchXml).then(
          function success(result) {
           console.log(result,'success')
          },
          function (error) {
            console.log(error.message);
          }
        );
      })
  • let value = await 一个promise函数

    value就是promise内部resolve的值

陷阱

如果循环中await语句,那需要使用for循环, 不能用map和forEach来循环,因为他会立刻返回不会等待

for await也行

所以在刚刚的例子中,应该用传统的for循环来遍历

  • 如果坚持用map,那么需要在外层使用Promise.all()

总结

  • fetch()基于Promise,对于请求返回的数据需要json()格式化
  • 获取async函数的返回值:
    • async内部中直接return
    • 外部用then()方法接收
  • Promise是一个对象
  • new Promise( (resolve, reject) => {} )
    • new的同时,会立即执行括号内的函数
    • 通过调用resolve()reject()返回异步操作的执行结果
  • .then()方法 接收Promise对象成功的返回值
    • 链式调用
  • .catch()方法 接收Promise对象失败的返回值
    • 捕捉错误

不存在十全十美的文章,就如同不存在彻头彻尾的绝望。

Life is hard, keep learning!

转载自:https://juejin.cn/post/7281208218176126976
评论
请登录