Promise学习笔记(一)
前言
一开始学习前端的时候,很多技术都是学习其用法,实际上很少去了解其原理,因此在空闲时,去写一些笔记记录一下自己对一些常用技术的原理理解。
什么是Promise?
Promise 是ES6提供的一个对象,Promise对象代表了未来将要发生的事件,用来传递异步操作的消息;常用在网络请求中。
Promise对象的状态不受外界影响,它有三种状态
· pending 进行中
· fulfilled 已成功
· rejected 已失败
Promise的状态只能由异步操作的结果决定。并且,Promise对象的状态既定,便不会再发生改变,且任何时候都能够得到其结果。Promise的状态改变通常只有 pending——fulfulled || pending——rejected。
Promise的优缺点
Promise对象可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。而且Promise对象提供了统一的接口,使得控制异步操作更加容易。
但是,Promise一旦新建就会立即执行,中途是无法取消的。其次,若不设置回调函数,Promise内部抛出的错误,是不会反应到外部(由于它内部不会受到外部的影响)。当Promise对象处于pending状态时,是无法得知目前进展到哪一个阶段。
Promise基础使用
使用一个东西的时候,我们常常需要了解这个东西内部提供了什么给我调用,所以先看一下Promise。
通过打印可以看出来,Promise是一个构造函数,它本身有all、reject、resolve方法,原型上还有then、catch等方法。所以想要创建一个Promise,使用new关键字即可。
let pro = new Promise (function (resolve, reject) { setTimeout (function () { console.log('Promise执行完毕') resolve('返回数据,通知回调执行') }, 1000) })
Promise的构造函数接收一个函数作为参数,函数传入了两个参数,分别为 resoleve 和 reject,前者代表了异步操作成功(pending—fulfilled)的回调函数,后者代表了异步操作失败(pending—rejected)的回调函数。
上面的代码,执行了一个异步操作,也就是定时器,在1秒后,输出“Promise执行完毕”,并且调用resolve方法。
实际上,当我们使用new关键字创建Promise对象时,被当做参数的函数传进去的时候已经执行了。所以我们使用Promise的时候,一般当做变量存放在一个函数中,在需要的时候再去运行这个函数。
function go () { let pro = new Promise (function (resolve, reject) { setTimeout (function () { console.log('Promise执行完毕') resolve('返回数据,通知回调执行') }, 1000) }) return pro }
那再看回来,为什么我们要把Promise包在函数中,还有就是resolve在这里面是什么作用。
上面的截图中,我们知道了Promise实际上是一个构造函数,可以调用then、catch方法。当我们将Promise包在函数中,我们可以这样使用
function go () { let pro = new Promise (function (resolve, reject) { setTimeout (function () { console.log('Promise执行完毕') resolve('返回数据,通知回调执行') }, 1000) }) return pro } go().then(function(data){ console.log('在这执行后续的操作,data是resolve传递的参数') })
看了上面这段代码,就懂了,then里面的函数实际上差不多是我们平时使用的回调函数。这个时候,可能会有个疑惑,既然这样子的用法,跟我们平时调用方法再写回调函数没什么区别,为什么还要大费周折地去用Promise?那再往回调里去想,如果有多层回调,而且回调本身也是一个异步操作呢?如果按照传统的写法来处理,会进入回调地狱,后期维护成本会很大,维护难度高,而Promise可以在then中继续写Promise对象并返回,然后继续调用then来进行回调操作,可以避免上述问题。
看到这里,我们似乎忘记了什么,emmmm..... 就是reject。那我们看一下下面的代码,很容易就理解了,这里使用一段ajax请求来写。
function ajax(URL) { return new Promise(function (resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = function () { if (req.status === 200) { resolve(req.responseText); } else { reject(new Error(req.statusText)); } }; req.onerror = function () { reject(new Error(req.statusText)); }; req.send(); }); } var URL = "请求地址"; ajax(URL).then( function success(data){ console.log('resolve') }, function fail(reason, data) { console.log('reject') } )
请求成功时,我们会用resolve传递成功的返回值去进行回调操作,失败或者出现异常时,则使用reject传递参数。在代码中,可以看到,then方法中接收了两个函数作为参数,第一个为resolve的回调,第二个为reject的回调。
上述则是个人对于Promise基础使用的一些心得。