ES6之Promise原理及常用的api

前言:

1.Promise原理解析

2.后面部分讲 then,resolve与reject,all,race的操作

一.Promise原理

先看原理图:

①执行new Promise时会返回一个空状态(pending挂起状态),此时返回的是undefined(既不是成功,也不是失败

②Promise内部有两个方法,resolve和reject。resolve是将pending状态变为完成(fulfilled)状态,返回结果(result);而reject是将pending状态变为拒绝(rejected)状态,返回结果error。切记,状态是不可逆的,只能从pending到fulfilled或rejected。

二.Promise.prototype.then(onFulfilled, onRejected)方法

1.只要是promise对象就支持Promise语法,就能用then。

2.then支持两个参数,两个参数onFulfilled,onFulfilled都是函数类型的,而且onFulfilled和onFulfilled对应Promise的resolve和reject两个方法,因为这两个方法返回两个不同的状态.

3.如果then里面传的是非函数,就会返回一个空的Promise对象,这家就能保证调用then就一定能够返回一个then对象,这样子就能完全保证我们能够实用连续的then的链式调用.

代码1:

function loadScript (src) {
  return new Promise((resolve, reject) => {
    let script = document.createElement("script");
    script.src = src;
    script.onload = () => resolve(src);
    script.onerror = (err) => reject(err);
    document.head.append(script);
  })
}

loadScript("./1.js")
  .then(loadScript("./2.js"))
  .then(loadScript("./3.js"))

//返回1 2 3
//./1.js ./2.js ./3.js均来自静态文件

说明:①上面代码中,then里面提供非函数 (nonfunction) 参数,那么 then 方法将会丢失关于该状态的回调函数信息,但是并不会产生错误,上面代码返回的pending状态。

 

代码2:

function loadScript (src) {
  return new Promise((resolve, reject) => {
    let script = document.createElement("script");
    script.src = src;
    script.onload = () => resolve(src);
    script.onerror = (err) => reject(err);
    document.head.append(script);
  })
}
  
loadScript("./1.js")
    .then(() => {
      // 如果不加return则返回一个空的Promise对象,因为loadScript('./4.js')不是函数
      // 如果加上return就是返回一个新的Promise实例去影响下一个then的状态
      return loadScript('./42.js')
    }, (err) => {
      console.log(err)
    })
    .then(() => {
      loadScript('./3.js')
    }, (err) => {
      console.log(err)
    })

说明:

①如果不加return,依旧是个非函数(因为loadScript('./4.js')不是函数),则返回一个空的Promise对象。

②如果加上return就是返回一个新的Promise实例去影响下一个then的状态

 

代码3:then的正规操作

function loadScript (src) {
  return new Promise((resolve, reject) => {
    let script = document.createElement("script");
    script.src = src;
    script.onload = () => resolve(src);
    script.onerror = (err) => reject(err);
    document.head.append(script);
  })
}
  
loadScript("./4.js").then((value) => {
    console.log(value)
  }, (err) => {
    console.log(err)
  })

结果:

说明:这是正常执行的结果,里面写的都是函数

三、Promise.resolve与Promise.reject的使用

        一般情况下我们都会使用 new Promise() 来创建 Promise 对象,但是除此之外我们也可以使用其他方法。在这里,我们将会学习如何使用 Promise.resolve 和 Promise.reject 这两个静态方法。

代码:

  function cap (type) {
    if(type){
      return Promise.resolve(42)
    } else {
      return Promise.reject(new Error("出错了"))
    }
  }

  cap(0).then((value) => {
    console.log(value)
  }, (err) => {
    console.log(err)
  })

结果:

说明:

①如果直接返回的是数据,而且又想使用then方法,可以直接用静态方法里面写入数据,然后用then去调用,如上代码所示。

四、Promise.prototype.catch()方法

      捕获异常是程序质量保障最基本的要求,可以使用 Promise 对象的 catch 方法来捕获异步操作过程中出现的任何异常。

代码1:

function loadScript (src) {
  return new Promise((resolve, reject) => {
    let script = document.createElement("script");
    script.src = src;
    script.onload = () => resolve(src);
    script.onerror = (err) => reject(err);
    document.head.append(script);
  })
}
 
 loadScript("./1.js")
    .then(() => {
      return loadScript('./42.js')
    })
    .then(() => {
      loadScript('./3.js')
    }).catch(err => {
      console.log(err)
    })

结果:

说明:catch() 方法返回一个Promise,并且处理拒绝的情况。它的行为与调用Promise.prototype.then(undefined, onRejected) 相同。

代码2:代码比较

// 代码1
function test () {
  return new Promise((resolve, reject) => {
    throw new Error('wrong')
  })
}

test().catch((e) => {
  console.log(e.message) // wrong
})

// 代码2
function test () {
  return new Promise((resolve, reject) => {
    reject(new Error('es'))
  })
}

test().catch((e) => {
  console.log(e.message) // es
})

问题:这个代码展示了如何使用 catch 捕获 Promise 对象中的异常,有的同学会问 catch 捕获的是 Promise 内部的 Error 还是 Reject?上面的示例既用了 reject 也用了 Error,到底是哪个触发的这个捕获呢?

答:如上代码,代码1对比着上个代码2就能明显感受出来的,throw Error 和 reject 都触发了 catch 的捕获,而第2个用法中虽然也有 Error 但是它不是 throw,只是 reject 的参数是 Error 对象,换句话说 new Error 不会触发 catch,而是 reject。

说明:不建议在 Promise 内部使用 throw 来触发异常,而是使用 reject(new Error()) 的方式来做,因为 throw 的方式并没有改变 Pronise 的状态

五、Promise.all(promiseArray)方法

var p1 = Promise.resolve(1)
var p2 = Promise.resolve(2)
var p3 = Promise.resolve(3)
Promise.all([p1, p2, p3]).then(function (results) {
  console.log(results) // [1, 2, 3]
})

 说明:

①Promise.all 生成并返回一个新的 Promise 对象,所以它可以使用 Promise 实例的所有方法。参数传递promise数组中所有的 Promise 对象都变为resolve的时候,该方法才会返回, 新创建的 Promise 则会使用这些 promise 的值。

②如果参数中的任何一个promise为reject的话,则整个Promise.all调用会立即终止,并返回一个reject的新的 Promise 对象。

③由于参数数组中的每个元素都是由 Promise.resolve 包装(wrap)的,所以Paomise.all 可以处理不同类型的 promose对象。

六、 Promise.race(promiseArray)方法

场景:比如说有两条线路,你想快速的获得某一条线路等等,优点像CDN

返回值:一个待定的 Promise 只要给定的迭代中的一个promise解决或拒绝,就采用第一个promise的值作为它的值,从而异步地解析或拒绝(一旦堆栈为空)。

代码:

  const fn1 = () => {
    return new Promise((resolve, reject) =>{
      setTimeout(()=>{
        resolve(111)
      },2000)
    })
  }

  const fn2 = () => {
    return new Promise((resolve, reject) => {
      setTimeout(() =>{
        resolve(222)
      }, 1000)
    })
  }

  Promise.race([fn1(), fn2()]).then((value) => {
    console.log(value)//222
  })
  

说明:

①因为fn2的时间在1000mm,而fn1的时间在2000mm,所以fn2快于fn1,所以fn2先返回了

七、用Promise写一个接口

  function getUrl (url) {
    return new Promise((resolve, reject) => {
      let xml = new XMLHttpRequest()
      xml.onreadystatechange = function() {
        if (xml.ready === 4) {
          if (xml.status === 200) {
            resolve(JSON.parse(xml.responseText))
          }
          else if (xml.status === 404) {
            reject(new Error('错误信息404'))
          }
        }
      }
      xml.send(null)
    })
  }
  
  const url = './jsonp.json'
  getUrl(url).then((res) => {
    console.log(res)
  })

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Promise是一种异步编程的解决方案,它可以让我们更方便地处理异步操作。Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。当Promise处于pending状态时,我们可以使用then方法来注册回调函数,当Promise状态变为fulfilled或rejected时,对应的回调函数就会被调用。Promise原理是基于事件循环机制,它通过微任务和宏任务的方式来实现异步操作。当Promise状态变为fulfilled或rejected时,会将对应的回调函数放入微任务队列中,等待当前任务执行完毕后立即执行;而当我们使用setTimeout等异步API时,会将对应的回调函数放入宏任务队列中,等待事件循环机制执行。这样就可以保证异步操作的顺序性和可靠性。 ### 回答2: ES6中的Promise是一种异步编程的解决方案。它可以解决回调函数嵌套过深、代码可读性差、错误处理困难、无法取消等问题,使异步操作更为简洁、可读和易于维护。Promise对象有三种状态:Pending(等待)、Resolved(已完成)和Rejected(已拒绝)。当Promise状态由Pending变为Resolved或Rejected时,Promise对象会执行相应的操作。 Promise内部有两个重要的执行环节:Promise的实例化和Promise的处理。 在Promise实例化的过程中,需要传入一个函数作为参数。这个函数有两个参数,分别是resolve和reject。resolve参数用于处理Promise成功时的情况,reject参数用于处理Promise失败时的情况。当Promise内部执行完resolve或reject函数后,Promise会立即转换为Resolved或Rejected状态。 在Promise的处理过程中,主要是通过对Promise实例进行链式调用来处理异步操作。由于Promise对象有then方法,所以可以通过链式调用来解决异步操作。 例如: ```js new Promise(function(resolve, reject) { setTimeout(() => resolve(1), 2000); // 2 秒后返回1 }).then(function(result) { console.log(result); // 输出1 return result * 2; }).then(function(result) { console.log(result); // 输出2 return result * 2; }).then(function(result) { console.log(result); // 输出4 return result * 2; }); ``` 以上面的代码为例,Promise对象首先会等待2秒钟,然后返回1。接下来,通过链式调用then方法,依次输出其结果2、4、8。 总体来说,Promise解决了异步操作中回调函数嵌套和错误处理的问题,使得异步操作更为直观和易于维护。同时,Promise也是语言内置的,相比于外部库,更为高效和稳定。 ### 回答3: PromiseES6中的一项新特性,它有助于解决JS中的异步编程问题。Promise可以看作是一个容器,可以保存某个未来才会结束的事件(通常是一个异步操作)的结果。Promise对象提供了一些接口用于获取异步操作的结果,同时还提供了链式调用的语法,可以将多个异步操作按照一定的顺序进行组合,方便程序员进行复杂的异步编程。 Promise有三个状态:Pending(进行中)、Fulfilled(已成功)和Rejected(已失败)。当一个Promise实例产生结果后,它就会从Pending状态转化为Fulfilled或Rejected状态,不再有其他状态转换。Promise可以通过then方法注册回调函数,分别对应Fulfilled和Rejected状态,回调函数的参数均为Promise的结果。 Promise的作用是在异步操作中解决回调地狱的问题,将异步代码用链式调用的语法进行串联,简化了异步操作的处理。另外,由于Promise是基于链式调用的设计,使得多个异步操作之间可以被串联起来,每个操作的回调函数都通过链式调用的方式进行设置,可以十分直观地描述多个异步操作的关系和完成的顺序。 总结:PromiseES6中用于解决异步编程问题的新特性,它可以将异步操作进行链式调用,解决回调地狱的问题,同时利用状态转换的特性,可以更加方便地对异步操作的结果进行处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值