Promise

作者: 凉城十月 | 来源:发表于2021-10-07 19:55 被阅读0次

    具体可以参考阮一峰的Promise

    看看一个例子

    function fn1() {
      setTimeout(()=>{
        console.log('fn1')
      }, 1000)
    }
    
    function fn2() {
      setTimeout(()=>{
        console.log('fn2')
      }, 1000)
    }
    
    function fn3() {
      setTimeout(()=>{
        console.log('fn3')
      }, 1000)
    }
    

    对于以上代码如何实现: 1秒钟之后输出 fn1, 再过疫苗输出 fn2, 再过1秒输出 fn3 ?

    可如下改装:

    function fn1(callback) {
      setTimeout(()=>{
        console.log('fn1')
        callback()
      }, 1000)
    }
    
    function fn2(callback) {
      setTimeout(()=>{
        console.log('fn2')
        callback()
      }, 1000)
    }
    
    function fn3() {
      setTimeout(()=>{
        console.log('fn3')
      }, 1000)
    }
    
    
    
    fn1(function(){
      fn2(function(){
        fn3()
      })
    })
    

    回调地狱!

    什么是Promise

    Promise是一个对象,对象里面存储一个状态,这个状态是可以随着内部的执行转化的,为以下三种状态之一:
    等待态(Pending)、完成态(Fulfilled)、拒绝态(Rejected)

    一开始,我们先设置好等状态从 pending 变成 fulfilled 和 rejected 的预案(当成功后我们做什么,失败时我们做什么)。

    Promise 启动之后,当满足成功的条件时我们让状态从 pending 变成 fullfilled (执行 resolve);当满足失败的条件,我们让状态从 pending 变成 rejected(执行 reject)

    Promise 范例

    范例1

    Promise.prototype.then / Promise.prototype.catch

    function getIp() {
      var promise = new Promise(function(resolve, reject){
        var xhr = new XMLHttpRequest()
        xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getIp', true)
        xhr.onload = function(){
          var retJson = JSON.parse(xhr.responseText)  // {"ip":"58.100.211.137"}
          resolve(retJson.ip)
        }
        xhr.onerror = function(){
          reject('获取IP失败')
        }
        xhr.send()
      })
      return promise
    }
    
    function getCityFromIp(ip) {
      var promise = new Promise(function(resolve, reject){
        var xhr = new XMLHttpRequest()
        xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getCityFromIp?ip='+ip, true)
        xhr.onload = function(){
          var retJson = JSON.parse(xhr.responseText)  // {"city": "hangzhou","ip": "23.45.12.34"}
          resolve(retJson.city)
        }
        xhr.onerror = function(){
          reject('获取city失败')
        }
        xhr.send()
      })
      return promise
    }
    function getWeatherFromCity(city) {
      var promise = new Promise(function(resolve, reject){
        var xhr = new XMLHttpRequest()
        xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getWeatherFromCity?city='+city, true)
        xhr.onload = function(){
          var retJson = JSON.parse(xhr.responseText)   //{"weather": "晴天","city": "beijing"}
          resolve(retJson)
        }
        xhr.onerror = function(){
          reject('获取天气失败')
        }
        xhr.send()
      })
      return promise
    }
    
    getIp().then(function(ip){
      return getCityFromIp(ip)
    }).then(function(city){
      return getWeatherFromCity(city)
    }).then(function(data){
      console.log(data)
    }).catch(function(e){
      console.log('出现了错误', e)
    })
    

    Promise.all
    Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。

    范例2

    function getCityFromIp(ip) {
      var promise = new Promise(function(resolve, reject){
        var xhr = new XMLHttpRequest()
        xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getCityFromIp?ip='+ip, true)
        xhr.onload = function(){
          var retJson = JSON.parse(xhr.responseText)  // {"city": "hangzhou","ip": "23.45.12.34"}
          resolve(retJson)
        }
        xhr.onerror = function(){
          reject('获取city失败')
        }
        xhr.send()
      })
      return promise
    }
    
    var p1 = getCityFromIp('10.10.10.1')
    var p2 = getCityFromIp('10.10.10.2')
    var p3 = getCityFromIp('10.10.10.3')
    
    //Promise.all, 当所有的 Promise 对象都完成后再执行
    Promise.all([p1, p2, p3]).then(data=>{
      console.log(data)
    })
    

    Promise.race
    顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

    function getCityFromIp(ip) {
      var promise = new Promise(function(resolve, reject){
        var xhr = new XMLHttpRequest()
        xhr.open('GET', 'https://easy-mock.com/mock/5ac2f80c3d211137b3f2843a/promise/getCityFromIp?ip='+ip, true)
        xhr.onload = function(){
          var retJson = JSON.parse(xhr.responseText)  // {"city": "hangzhou","ip": "23.45.12.34"}
          resolve(retJson)
        }
        xhr.onerror = function(){
          reject('获取city失败')
        }
        setTimeout(()=>{
          xhr.send()
        }, Math.random()*1000)
    
      })
      return promise
    }
    
    var p1 = getCityFromIp('10.10.10.1')
    var p2 = getCityFromIp('10.10.10.2')
    var p3 = getCityFromIp('10.10.10.3')
    
    //Promise.race, p1p2p3只要有一个出结果了就执行
    Promise.race([p1, p2, p3]).then(data=>{
      console.log(data)
    })
    

    对于开头回调地狱的解决

    function fn1() {
      return new Promise((resolve, reject)=>{
        setTimeout(()=>{
          console.log('fn1...')
          resolve()
        }, 1000)    
      })
    }
    
    function fn2() {
      return new Promise((resolve, reject)=>{
        setTimeout(()=>{
          console.log('fn2...')
          resolve()
        }, 1000)    
      })
    }
    
    function fn3() {
      return new Promise((resolve, reject)=>{
        setTimeout(()=>{
          console.log('fn3...')
          resolve()
        }, 1000)    
      })
    }
    
    function onerror() {
      console.log('error')
    }
    
    fn1().then(fn2).then(fn3).catch(onerror)
    

    相关文章

      网友评论

          本文标题:Promise

          本文链接:https://www.haomeiwen.com/subject/snuonltx.html