Promise使用

2018-10-24  本文已影响0人  西域战神

Promise含义

Promise是一种异步编程的解决方案,它可以获得异步操作的消息。
promise有三种状态:pending(进行中)、fullfilled(已成功)、reject(已失败)。只有异步操作的结果才能决定promise的状态。

Promise 操作

在promise出现以前,假设我们需要输出fn1的结果后的一秒输出fn2的结果,然后再输出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可以很好的解决这种情况,我们可以做如下改造:

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 error () {
    console.log('error')
}

然后进行调用:

fn1().then(fn2).then(fn3).catch(error)
回调

这样就很好的解决了“回调地狱”问题,代码变得更加清晰,可读性更好。

promise的一个更加重要的作用是可以让我们在异步像同步函数一样获取return的值。

比如我们手机上的外卖软件,它是先获取我们手机的ip地址,通过ip地址来取得城市的名称,然后返回我们附近的商家信息。

function getIp() {
  let promise = new Promise(function(resolve, reject){
    let xhr = new XMLHttpRequest()
    xhr.open('GET', 'url/api/ip', true)
    xhr.onload = function(){
      var retJson = JSON.parse(xhr.responseText)  
      resolve(retJson.ip)
    }
    xhr.onerror = function(){
      reject('获取IP失败')
    }
    xhr.send()
  })
  return promise
}

function getCity(ip){
    let promise = new Promise(function(resolve, reject){
    var xhr = new XMLHttpRequest()
    xhr.open('GET', 'url/api?ip='+ip, true)
    xhr.onload = function(){
      let retJson = JSON.parse(xhr.responseText) 
      resolve(retJson.city)
    }
    xhr.onerror = function(){
      reject('获取city失败')
    }
    xhr.send()
  })
  return promise
}
function getShopsFromCity(city) {
  var promise = new Promise(function(resolve, reject){
    let xhr = new XMLHttpRequest()
    xhr.open('GET', 'url/api/shops?city='+city, true)
    xhr.onload = function(){
      var retJson = JSON.parse(xhr.responseText)   
      resolve(retJson)
    }
    xhr.onerror = function(){
      reject('获取周边商家失败')
    }
    xhr.send()
  })
  return promise
}

getIp().then((ip)=>{
    return getCity(ip)
}.then((city)=>{
    return getShopsFromCity(city)
}).then((res)=>{
        console.log(res)
    }
}

这样我们就可以获得商家信息了,通过promise很好的解决了return的问题。

promise常用函数

all

当前的promise对象都执行完以后再进行操作

Promise.all([p1, p2, p3]).then(data=>{
  console.log(data)
})

race

当前的promise对象,只要其中一个状态改变,那个率先改变的值就传给回调函数。

Promise.race([p1, p2, p3]).then(data=>{
  console.log(data)
})

通过promise封装axios操作

在实际开发中,我们通常使用axios这个基于promise的HTTP库,来创建浏览器的XMLHttpRequst。如果每次都像下面这样使用,代码会非常繁琐:

  axios.get('/api/home?page=' + page).then((res) => {
      const result = res.data.data
      const action = addHomeList(result, page+1)
      dispatch(action)
    })

首先我们先定义axios的一些常用属性

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
axios.defaults.baseURL = baseURLConfig.baseURL
axios.defaults.withCredentials = true

然后export default 一个默认是”GET“请求的request函数

export default function request(url, type = 'GET', data = {}) {
    return new Promise((resolve, reject) => {
    let option = {
      url,
      method: type,
      validateStatus (status) {
        return (status >= 200 && status < 300) || status === 400
      }
    }
    if (type.toLowerCase() === 'get') {
      option.params = data
    } else {
      option.data = data
    }
    axios(option).then(res =>{
      if (res.status === 200) {
        resolve(res.data)
      } else {
        reject(res.data)
      }
    }).catch(err=>{
      reject({msg: '网络异常:'+ err})
    })
  })
}

然后在组件中,就可以像下面这样使用了,代码可读性更好了

request(url,type,{}).then((res)=>{  console.log(res.data) })
  .catch(err=>{
    console.log(error)
})
上一篇 下一篇

猜你喜欢

热点阅读