Promise

61 阅读3分钟

Promise介绍

Promise 是异步编程的一种更优雅的解决方案,比传统的解决方案——回调函数——更合理和更强大。简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
简单理解为: promise是对异步操作的封装,封装异步文件读写,定时器、ajax异步网络请求...

image.png

语法: ES6新增一个对象

作用: 对异步任务进行封装,更好的更优雅的处理异步任务结果 回调函数

ajax({
    success:function(data){}
})
setTimout(function(){
                  
},1000)

使用:

let promise = new Promise(function(resolve,reject){
    // resolve 函数 处理异步任务成功的结果  resolve('成功')
    // reject 函数  处理异步任务失败的结果  reject('失败')
    
    // 异步任务封装
    setTimeout(function(){
        if(true){
            resolve('成功')
        } else {
            reject('失败')
        }
    },1000)
})

promise.then(function(result){
    result=>成功
})
promise.catch(function(error){
    error=>失败
})

基本用法

异步ajax封装

**
*promise 对ajax异步网络请求封装
*创建promise对象,封装具体异步操作
*/
const promise = new Promise(function (resoloved,rejected){
    // 1. XmlHttpRequest
    // 2. open()建立连接
    // 3. send()发送请求
    //4.处理响应
    
    //1.实例XMLHttpRequest对象
    let xhr = new window. XMLHttpRequest()
    //2.建立连接
    xhr.open( 'GET',"http://10.7.176.118:8089/ api/list')
    //3.发送请求
    xhr.send()
    //4.处理响应数据
    xhr.onreadystatechange = function (e) {
        e = e ll window. event
        target = e.target ll e.srcElementif (target.readyState == 4) {
            //响应成功
            if (target.status == 200){
                resoloved(target.responseText)
            }else{
                rejected('网络出错')
            }
        }
    }
})

Promise链式调用

要读取三个文件,第一个文件读取完成后,再读取第二个文件,然后再是第三个文件。这时引起 回调函数层层嵌套问题,回调地狱,其实就是回调函数嵌套过多导致的

promise解决回调嵌套问题

new Promise(function (resolve, reject) {
    ajax({
        url:'第一个请求', 
        success (res) {
            resolve(res)
        }
    })
}).then(function (res) { 
    //准备发送第二个请求
    return new Promise(function (resolve, reject) {
        ajax({
            url:'第二个请求" ,
            data: {a:res.a, b:res.b},
            success (res) {
                resolve(res)
            }
        })
    })
}).then(function (res) {
    ajax ({
        url: '第三个请求',
        data: {a: res.a, b: res.b},
        success (res) {
            console.log(res)
        }
    })
})

promise封装ajax

/**
 * 封装一个函数获取promsie对象, promise对象封装处理网络请求异步任务
      options = {
          method:'get',
          url:''
          data:{}
      }
 * @param {*} options 
 * @returns 
 */
function myPromise(options) {
return new Promise((resolve, reject) => {
        jax({
	method: options.method,
	url: options.url,
	data: options.data,
	success: function (result) {
                resolve(result)
            },
	fail:function(error){
                reject(error)
	}
        })
})
}

function ajax(options) {
// 1. 创建XMLHttpRequest
let xhr = new XMLHttpRequest()
let param = formateParam(options.data) // name=jack&age=18
    let method = options.method.toUpperCase()

    // 2. 建立连接
if (method == 'GET') {
        xhr.open(options.method, options.url + '?' + param)
        // 3. 发送请求
        xhr.send()
} else if(method == 'POST'){
        xhr.open(options.method,options.url)
        xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
        xhr.send(param)
    }

// 4. 接收响应数据
xhr.onreadystatechange = function () {
        // 4.1 是否响应完成
        if (xhr.readyState === 4) {
	// 4.2 是否成功响应
	if (xhr.status === 200) {
                let data = xhr.responseText // 响应内容
                data = JSON.parse(data)
                options.success(data)
	} else {
                // alert('网络出错 ' + xhr.status)
                options.fail('网络出错 ' + xhr.status)
	}
        }
}
}

/**
 * 格式化参数
 *  {name:'jack',age:18}  =>  name=jack&age=18
 *   遍历对象,属性转换成名称=值形式,存储到数组, 再将数组元素用&符号拼接join('&)
 *    ['name=jack','age=18']  ->
 */
function formateParam(obj) {
let arr = []
for (const key in obj) {
        let item = `${key}=${obj[key]}` // name=jack   age=18
        arr.push(item) // ['name=jack','age=18;]
}
return arr.join('&') // name=jack&age=18
}

Promise方法

  • Promise.resolve方法

      var p = Promise.resolve('Hello');
      p.then(function (s) {
          console.log(s)
      });
      // Hello
    

上面代码生成一个新的Promise对象的实例p,它的状态为fulfilled,所以回调函数会立即执行,Promise.resolve方法的参数就是回调函数的参数。
如果Promise.resolve方法的参数是一个Promise对象的实例,则会被原封不动地返回。

  • Promise.reject方法

      var p = Promise.reject('出错了');
      p.then(null, function (s) {
          console.log(s)
      });
      //出错了
    

Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。
Promise.reject方法的参数reason,会被传递给实例的回调函数。

  • Promise.race

      //竞争执行谁执行,先返回谁结果
      Promise.race([promise1,promise2]).then(data => {
          console.log(data);
      })
    
  • Promise.all

      //同时并发执行,返回数组形式结果
      Promise.all([promise1,promise2]).then(datas => {
          console.log(datas);
      })