(Day24) 处理非同步的 Promise

前言

在过去 JS 要处理 Ajax 这个非同步语法,会很容易用到 Callback 写法,而 Callback 不但不好管理,还容易写成 Callback Hell,如图:

幸好 ES6 新增了 Promise ,对於 JS 这个单执行序的语言 Promise 非常实用。
Promise 直接翻译成中文会是承诺 ,而 Promise 的使用结果也就分成两种

  • 达成承诺,使用 resolve()
  • 承诺失败,使用 reject()

实际使用 Promise

而要使用 Promise 大致上分为两个步骤:

  • 使用 new Promise() 的函式建构式创造一个新的 Promise 物件
  • 实际执行上面提到的 Promise 物件

在创造函式建构式时,函式建构式会带上两个参数 resolvereject , 第一个参数是用来执行 成功的方法,第二个则是 失败的方法,这两个参数名称接可以自定义,不过实际开发时多数,仍会使用这个名称做命名。
(这边是把 Promise 写成函式方法,因此可以带入参数,在透过参数来做判断。)

function PromiseFn(String) {
	// 创造建构函式并带上 resolve 、 reject 参数
  return new Promise((resolve, reject) => {
    setTimeout(function () {
        // Promise 承诺的判断
      if (String.length >= 5) {
        resolve(`Promise 成功, ${ String } 共 ${ String.length } 个字 `)
      } else {
        reject('Promise 失败')
      }
    }, 2000);
  });
}

建立好 Promise 函式建构式後,便是执行 Promise 本身了,接者执行 Promise 本身时,我们可以使用 then()catch() 他们会分别接收 Promise 成功 以及 Promise 失败的结果,但他们需要写上一个 Callback Function ,若要显示 Promise 建构式中的 resolve()reject() 设定的资料,那麽会需要在 Callback Function 中带上一个参数,这些参数就会显示 resolve()reject() 设定的资料:

function PromiseFn(String) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      if (String.length >= 5) {
        resolve(`Promise 成功, ${ String } 共 ${ String.length } 个字 `)
      } else {
        reject('Promise 失败')
      }
    }, 2000);
  });
}

PromiseFn('test')// Promise 失败

.then((res)=>{ // 第一个参数会回传 resolve() 设定资料
  console.log(res)  
})
.catch((err)=>{
  console.log(err) // 第一个参数会回传 reject() 设定资料
})

PromiseFn('Ryder') //Promise 成功, Ryder 共 5 个字
.then((res)=>{
  console.log(res)
})
.catch((err)=>{
  console.log(err)
})

All 与 Race

扣除上面的 Promise 基本方法,Promise 还提供 Promise.all()Promise.race() 两种用法。

  • 使用 Promise.all() 时,会执行 Promise.all() 中所有的 Promise 方法,并将回传一个阵列,而这个阵列就是 resolve() 所提供的。
function PromiseFn(String) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      if (String.length >= 5) {
        resolve(`Promise 成功, ${ String } 共 ${ String.length } 个字 `)
      } else {
        reject('Promise 失败')
      }
    }, 2000);
  });
}

Promise.all([PromiseFn('Ryder'), PromiseFn('youtube')]).then((res)=>{
	console.log(res) //['Promise 成功, Ryder 共 5 个字 ', 'Promise 成功, youtube 共 7 个字 ']
})
  • Promise.race()Promise.all() 一样,会同时执行 Promise.race() 中所有 Promise 方法,但他只会回传最快执行完毕的 Promise 方法。
const p = new Promise((resolve) => {
  if (true) {
    resolve(`直接执行 Promise`)
  }
})
function PromiseFn(String) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      if (String.length >= 5) {
        resolve(`Promise 成功, ${String} 共 ${String.length} 个字 `)
      } else {
        reject('Promise 失败')
      }
    }, 2000);
  });
}

Promise.race([PromiseFn('Ryder'), p]).then((res) => {
  console.log(res) //直接执行 Promise
})

链式写法

上面介绍的 Promise.all() Promise.race() 都是会同时执行的方法,不过我们肯定会遇到需要依序执行 Promise 的状况,在过去使用 Callback Function 时就会写出超巢的 Callback Hell,不过 Promise 则提供了链式写法,可以轻松的达成需求。
要使用 Promise 的链式写法,只需要在 then() 中使用 return 并呼叫下一个 Promise 这样变能使用 .then() 不断串联下去。

const p = new Promise((resolve) => {
  if (true) {
    resolve(`直接执行 Promise`)
  }
})

function PromiseFn(String) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      if (String.length >= 5) {
        resolve(`Promise 成功, ${String} 共 ${String.length} 个字 `)
      } else {
        reject('Promise 失败')
      }
    }, 2000);
  });
}
PromiseFn('Ryder')
  .then((res) => {
    console.log(res) // Promise 成功, Ryder 共 5 个字
    return PromiseFn('youtube') // Promise 链式写法,可以不断写 Promise 下去。
  }).then((res) => {
    console.log(res)  // Promise 成功, youtube 共 7 个字 
    return p
  }).then((res) => {
    console.log(res) // 直接执行 Promise
  })

参考文献


<<:  [Day09] 第九章-Laravel 操作心得及资料来源补充

>>:  JS 09 - 类别函式

杂谈    

第43天~

这个得上一篇:https://ithelp.ithome.com.tw/articles/10258...

D23 - 彭彭的课程# Python 网路连线程序、公开资料串接(1)

今天开始来迎接双十连假 加油啊!! 今年最後一个年假了要好好珍惜XDD 今天要来opendata连线...

Day 26 一直线的前进_____ 不能断啊!

我们不能总在弹性限度里活动,要爆发,要超越,才会有质的提高。 《iT邦帮忙铁人赛的观点》(以下简称铁...

Day02:先生先生,请问你装了什麽进去?

Java,我相信如果去查维基百科,「物件导向」这4个字一定会在叙述的第一行。 换言之,在Java的世...

(MVC,JS)FormData 的运用

小弟是初新者,第一次写笔记,写不好请见谅也请多指教! 因为公司功能需求有去接触到,想说尝试做个笔记与...