Promise的理解与随手实例

我们 学习一个新的特性时,我习惯先了解他是什么, 有什么用

在 w3c中 可知 Promise 是 抽象异步处理对象以及对其进行各种操作的组件 . 他 多用于 处理回调地狱 . 什么是回调地狱呢? 即 嵌套多个回调 如果 有多个回调互相嵌套 则 会难以调试与 理解 增大代码维护的难度与可读性

使用 promise 就能解决这个问题 , promise 可以是一个占位符,表示异步操作的执行结果, 函数可以返回一个promise 而不 是 传递一个回调

promise 都会有一个 短暂的生命周期

有两种状态

初始的挂起未决状态 --> 异步未结束

已决的状态 ---> 异步操作结束

处于 已决转态 会有两种情况

1  已经成功完成的异步操作

2 可能是一个错误或者其他的原因导致了 异步的操作没成功

此时 promise中有个 [ [PromiseState]] 属性 会被设置 为 pending fulfilled 或者 rejected , 以反映 promise 的状态处于 哪一步 . 但这个属性 并不在 promise 对象上面 暴露. 因此 无法 判断 他处于那种状态

但此时其 提供了

then() 方法 

他在所有的promise 上都存在. 并且接受两个参数  .

  	第一个 参数 是promise 被完成时 调用的 函数  , 异步操作的结果数据  
  		都会传入 完成函数

  	第二个函数 则是 promise 被拒绝的时调用的函数, 也会将失败的参数数据   

	这两个参数是可选的  可以自由的监听 完成 和失败的处理函数

catch 方法 

Promise有catch()方法,等同于只传递拒绝处理函数给then()方法:

用处
比如 Vue 发起axios 的请求时 正常来说异步 返回的是 一个 回调函数. 但此时 使用 promise 直接返回一个 axios.get或者 axios.post 让这个 promise 对象 (axios是promise对象 )自己 进行 成功 ( .then() ) 之后的 处理 或者失败(.catch() ) 的提示

他人总结:
Promise 具有三种状态:挂起、已完成、已拒绝。一个 Promise 起始于挂起态,并在成功时转为完成态,或在失败时转为拒绝态。 then() 方法允许你绑定完成处理函数与拒绝处理函数,而 catch() 方法则只允许你绑定拒绝处理函数;

能够将多个Promise串联起来组成Promise链,并且能够在中间传递值,甚至是传递Promise对象。 then() 的调用都创建并返回了一个新的 Promise ,只有在前一个 Promise 被决议过,新 Promise 也会被决议。 同时也可以使用Promise.all()和Promise.race()方法来管理多个Promise

例子

/**
 * promise 对象是一个构造函数, 用来生成 promise 对象
 * 
 *  resolve 将 promise 对象的状态从 未完成=> 转变成 成功, 并且在 异步调用成功之后, 将成功之后的结果 传递出去
 *  reject 将 promise 对象的状态 从 未完成=> 转变成 失败, 并且在 异步调用失败的错误作为参数 传递出去  
 * 
 *  promise 实例生成之后 可以分别指定  resolve 状态和 reject 状态的 回调函数
 */
    // promise
    var promise = new Promise((resolve, reject) => {
        if (true) {
            resolve();
        } else {
            reject();
        }
    })

    // 例子 一
    function timeFun (ms) {
        return new Promise ((resolve, reject) => {
            setTimeout(resolve, ms, 'done');
        })
    }
    timeFun(100).then(resolve => {
        console.log(resolve) // done
    })

    // 例子二  // promise 一旦建立就会立即执行
    const promiseTwo = new Promise((resolve, reject) => {
        console.log("我是第一个输出的");
        resolve();
    })

    promiseTwo.then(res => {
        console.log('我是第三个输出的');
    })

    console.log('我是第二个输出的')

    /**
     * 输出结果
     *  promise.js:31 我是第一个输出的
        promise.js:39 我是第二个输出的
        promise.js:36 我是第三个输出的
        promise.js:26 done

        promise 新建之后会立即执行 , 首先输出第一 , promise 里面的 resolve 是异步方法, 所以先执行 所有同步再执行异步, 此时 会先输出 第二, 
        然后再输出 第三 , 100 之后 会再执行 done 
     */

     // 例子三  promise 实现操作 Ajax 操作
     let promiseAjax = function (url) {
        let promise = new Promise ((resolve, reject) => {
            // 新建一个 对象
            var xhr  = new XMLHttpRequest();
            // 请求方式
            xhr.open('GET', url);
            // 状态请求改变的回调
            xhr.onreadystatechange = handler;
            // 返回数据格式
            xhr.responseType = 'json',
            xhr.setRequestHeader('Accept', 'application/json');
            xhr.send();
            function handler() {
                if (this.status === 200) {
                    resolve(this.response);
                } else {
                    reject(new Error(this.statusText))
                }
            }
        })
        return promise
     }

     var url  = 'http://httpbin.org/get';
     promiseAjax(url).then(res => {
         console.log('res', res)
     }).catch(error => {
         console.log('error',error)
     })
     
     // 输出 res null  promise 中的 resolve 跟 reject 都 会带有参数回传 , 
     //一个成功之后的参数, 一个失败之后的, 成功的也可能是 一个 promise 实例, 如 Vue 中的 axios 实例

     /**
      * 要理解 promise 中的 then 方法, 该方法作用是在 Promise 实例状态改变时的回调函数 , then 方法的第一个参数 是 resolve(成功的) 状态的回调, 
      * 第二个参数 是 reject(失败的) 的 状态的回调 
      *  { 
      *     但是不推荐使用第二个参数-> 推荐使用 catch 进行捕获错误, 原因-> 因为promise的 状态一旦改变,就永久保持该状态, 使用 then 第二个参数识别错误,错误并不会一直传递,
      *     但Promise对象的错误具有传递性质,它会一直往下传递,直到被catch捕获到为止。
      *  }, 
      * 还有需要注意的是 then 方法返回的 还是一个 promise 对象. 
      * 所以我们可以使用  链式 写法, then 后面再跟 then 方法 (vue 的 axios 使用)
      * 
      * 如下
      * 
      */

      // then 链式写法
      promiseAjax(url).then(res => {
        console.log(1,res)
        return res
        }).then(val => {
            console.log(2, val) // 返回的是 与上面一直的结果   输出: 1 null 2 null 
        })

        // 错误捕获案例
        // 不推荐 的写法
        var p6 = new Promise((resolve, reject) => { });
        p6.then((data) => {
            // success
        }, (error)=>{
            // error
        });
        // 推荐 的写法
        p6.then((data) => {
            // success
        }).catch((error) => {
            // error
        })
        

这篇文章解析的更为 详细易懂.
https://www.jianshu.com/p/063f7e490e9a

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章