关于Promise的总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Promise的总结相关的知识,希望对你有一定的参考价值。

Promise是异步编程的一种“解决方案”,这里说的是一种解决方案,就是为了解决我们传统使用回调函数和事件来实现异步的复杂及不合理性。

从抽象上来说 Promise就是一个容器,里面存储了某个未来才会结束的事件(一个异步操作)的结果。

从语法上来说 Promise就是一个对象,从它我们可以获取异步操作的各种消息。它提供了统一的API,各种异步操作都可以用同样的方法来进行处理。

技术分享

从上图中我们看出来 Promise就是一个构造函数,自身有resolve,reject,all,race 等方法。原型上有then和catch方法, 也就是说所有Promise的实例都有then和catch方法。

首先来创建一个简单的 Promise对象 promise,这里我们使用定时器来模拟异步操作。

1 const promise = new Promise(function (resolve,reject) {
2         setTimeout(function () {
3             console.log(‘异步操作‘);
4             resolve(‘这是完成‘);
         reject(‘这是失败或者错误‘);  
5 },1000);
6 });

Promise构造函数接受一个‘函数类‘参数,这个函数有两个参数resolve和reject。

执行1秒之后返回———‘异步操作‘ ,并且调用resolve或者reject方法(这两个方法根据异步操作结果成功或者失败调用)。

也许可能对resolve和reject这两个方法有点不理解,这两个方法是干嘛用的,什么时候执行。在这之前先让我们来看一下Promise的三个特点。

1、Promise对象的状态是不受外界影响的,它代表一个异步操作,有三种状态:Pending(进行中),Fulfilled(已成功)和Rejected(已失败)。

>>resolve(成功)时会调用 onFulfilled,reject(失败)时会调用 onRejected。

>>只有异步操作的结果可以决定当前是哪一种状态(成功的结果我们去调用resolve,失败的结果我们去调用reject)。

 

2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。

3、上述代码中我们并没有执行这个对象,只是new 了一个Promise对象。也就是说一旦建立它就会立即执行。所以一般我们会在外面包裹一个函数,控制它什么时候执行。

function asyncFun() {
    const promise = new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log(‘异步操作‘);
            resolve(‘这是完成‘);
            reject(‘这是失败或者错误‘);
        }, 1000);
    });
    return promise;
}
//asyncFun.then(onFulfilled,onRejected);
asyncFun().then(function (data) {
    console.log(data);//这是完成
},function (data) {
    console.log(data);
});

上述代码中我们在promise对象的外层包装了一个函数asyncFun,返回promies对象。

对通过new生成的promise对象为了设置其结果在 resolve(成功) 或者 reject(失败)时调用的回调函数,我们可以使用asyncFun().then() 实例方法。

asyncFun().then(onFulfilled, onRejected)    resolve(成功)时onFulfilled会被调用,reject(失败)时onRejected会被调用。

onFulfilled, onRejected为可选参数,如果只想处理错误的结果,可以asyncFun().then(undefined, onRejected)这样使用,不过这种情况下建议使用另外一个方法:asyncFun().catch(onRejected)。

这时候你应该有所领悟了,原来then里面的函数就跟我们平时的回调函数一个意思,能够在asyncFun这个异步任务执行完成之后被执行,并且会拿到我们在asyncFun中调用resolve时传的的参数。这就是Promise的作用了,简单来讲,就是能把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。

OK ,再来看成功或者失败的例子。

function asyncFun() {
    const promise = new Promise(function (resolve, reject) {
        setTimeout(function () {
            let num = Math.ceil(Math.random()*10);
            if(num>=5){
                console.log(‘resolve‘);
                resolve(num);
            }else{
                console.log(‘reject‘);
                reject(‘数值小于5,失败了‘);
            }
        }, 1000);
    });
    return promise;
}
//asyncFun.then(onFulfilled,onRejected);
asyncFun().then(function (data) {
    console.log(data);
},function (data) {
    console.log(data);
});

asyncFun函数用来异步获取一个数值,如果这个这个值大于等于5,我们标识为‘成功’了,调用resolve方法改变Promise的状态。否则为失败,调用reject方法并传一个失败的参数,作为原因。

多次运行之后我们可能得到下面的执行结果:(resolve 6) 或者 (reject 4)

我们也可以把上面的reject回调改为catch(fn);如下:

asyncFun().then(function (data) {
    console.log(data);
}).catch(function(data){
    console.log(data);
});

与上面的操作结果是一样的。

最后我们再来看一下我们常见到的使用方式:Fn().then().then().then() ... .catch();链式调用方法。

我们还是使用上面的方法,多复制几个。

function asyncFun() {
    const promise = new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log(‘异步操作‘);
       resolve(‘resolve‘)
}, 1000); }); return promise; } function asyncFun1() { const promise = new Promise(function (resolve, reject) { setTimeout(function () { console.log(‘异步操作1‘);
       resolve(‘resolve1‘)
}, 1000); }); return promise; } function asyncFun2() { const promise = new Promise(function (resolve, reject) { setTimeout(function () { console.log(‘异步操作2‘)
       resolve(‘resolve2‘) },
1000); }); return promise; } //asyncFun.then(onFulfilled,onRejected); asyncFun().then(function (data) { console.log(data); return asyncFun1(); }).then(function (data) { console.log(data); return asyncFun2(); }).then(function (data) { console.log(data); }).catch(function (data) { console.log(data); });

这样我们就可以实现用同步的写法,实现层层回调异步的解决方案。而且能够根据上一个的操作状态控制下一个异步操作执行。

这样能够按顺序,每隔两秒输出每个异步回调中的内容,在asyncFun2中传给resolve的数据,能在接下来的then方法中拿到。

在then方法中我们也可以直接return 一个结果。例如:

asyncFun().then(function (data) {
    console.log(data);
    return ‘操作结果‘; //操作结果
}).then(function (data) {
    console.log(data);
    return asyncFun2();
}).then(function (data) {
    console.log(data);
}).catch(function (data) {
    console.log(data);
});

另外一点要说的是,如果我们在then 返回或者执行了一行错误的代码,也不会阻断代码的执行,而是会直接走到 catch()方法中。例如:

asyncFun().then(function (data) {
    console.log(data);
    console.log(abc);
    return ‘操作结果‘; //操作结果
}).then(function (data) {
    console.log(data);
    return asyncFun2();
}).then(function (data) {
    console.log(data);
}).catch(function (data) {
    console.log(data);
});

上面的abc变量未定义,但是没有阻断代码的执行,而是在catch里提示我们 abc is not defined。

 






以上是关于关于Promise的总结的主要内容,如果未能解决你的问题,请参考以下文章

关于Promise的总结

前端面试题之手写promise

谈谈promise

原谈谈promise

关于Promise的异步执行顺序理解

几个关于js数组方法reduce的经典片段