Promise

109 阅读3分钟

1.Promise是什么**

Promise 是异步编程的一种解决方案,从语法上讲,promise是一个对象,从它可以获取异步操作的消息

Promise 就是一个方法、一个js乃至一个页面的后续js代码的执行,都依赖于一个异步返回的数据,那么接下来所有的js代码都可以放在promise的then里面,链式调用。

2.为什么会有promise**

ES5中我们处理异步,大部分选择回调函数的请求方式,在请求到的成功回调函数里继续写函数,长此以往形成了回调地狱,层级少了当然还是可以凑合看的,但是多起来的话,那就难以维护了,无论是开发者自身还是同事来接手项目,都是极其无奈的。

所以就出现了Promise,最初用来结局回调地狱问题,一种异步请求方案,采用链式调用的方式,代码比较简洁明了且易维护。

3.promise怎么使用

说了那么多,那么Promise到底如何使用呢?我们在使用的时候实例化promise构造函数,resolve和reject是早就封装在构造函数里面的方法。new的时候写上就行了。

        ```js
            var request = function (type = 1) {

            return new Promise((resolve, reject) => {
                setTimeout(function () {
                    if (type == 1) {
                        resolve({
                            status: 200,
                            statusText: "success",
                            data: [
                                {
                                    username: "张三"
                                }
                            ]
                        });
                    }else{
                        reject({
                            status: 4001,
                            statusText:"error",
                            data: "出现错误"
                        })
                    }

                }, 2000);
            });
            }
            //返回成功效果执行resolve
            request().then(res => {
                console.log(res);
            }).catch(error => {
                console.log(error);
            })
            // 返回失败的效果 reject
            request(2).then(res => {
                console.log(res);
            }).catch(error => {
                console.log(error);
            })

4.promise的状态

    - Promise有三种状态  
        - pending - 进行中
        - fulfilled/resolved - 成功
        - rejected - 失败
    Promise对象,可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数,但Promise对象的
    状态不受外界影响,Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)
    和rejected(已失败),只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
    状态的改变(或者说决议)不可逆,一旦决议就不能再更改

5.promise如何解决异步

我们知道ES5中可以用回调的方式实现异步操作,但是如果回调我们多来几次,大家会不会发现回调的太多了吗?这就是大家所说的回调地狱;代码特别的多且不易读。所以ES6给我们提供了一个解决回调地狱的方法:promise;

    - promise是一种用异步的方式处理值的方法,promise是一个对象,解决层层嵌套问题

    - Promise有三个状态: 
        - 进行中: pending 
        - 成功: resovled
        - 失败: rejected

    - promise对象的方法:
        - then() 成功后执行; 如果有两个参数:第一个参数成功后执行,第二个参数失败后执行;
        - catch() 失败后执行;
        - Promise.all和promise.race参照前面的内容

    - 现在我们简单做一个练习 使用promise 加载一张图片;加载成功就将图片加载到body中,如果加载失败,提示失败;

        ```js
            var promise = new Promise(function (resolved, rejected) {
                var img = document.createElement('img');
                img.src = './1.png';
                img.onload = function () {
                    resolved(img)   //如果加载成功就返回resolved()
                }
                img.onerror = function () {
                    rejected('失败')    //如果加载成功就返回rejected()
                }
            })
            promise.then(function (msg) {
                document.body.appendChild(msg)
            },function (msg) {
                alert(msg)
            })
        ```

    - 那么怎么用promise解决异步问题呢?我们用promise解决ajax回调的问题

        ```js
            function ajaxPromise(url) {
                var promise = new Promise(function(resolved, rejected) {
                    var xhr = new XMLHttpRequest();
                    xhr.open('get', url);
                    xhr.send();
                    xhr.onreadystatechange = function() {
                        if (xhr.readyState === 4 && xhr.status === 200) {
                            resolved( xhr.responseText);   //告诉promise成功了
                        }
                    }
                    setTimeout(function () {//5秒后请求不到
                        rejected('error')  //告诉promise失败了
                    },5000)
                })
                return promise;
            }
            document.onclick = function () {
                var pro = ajaxPromise('data.json');
                pro.then(function (msg) {
                    alert(msg)   //如果路径对了,我们得到了数据
                },function (msg) {
                    alert(msg)  //如果路径错了我们弹出error
                })
            }
        ```

所以总的来说,promise主要是用来解决异步回调的回调嵌套过多,导致的地狱回调问题,可以使用then链式方式捕获最后的结果,比如我们用到的axios,vue-resource都是用的promise方式处理异步请求。