基本使用
// Promise 基本示例const promise = new Promise(function (resolve, reject) {// 这里用于“兑现”承诺resolve(100) // 承诺达成// reject(new Error('promise rejected')) // 承诺失败})promise.then(function (value) {// 即便没有异步操作,then 方法中传入的回调仍然会被放入队列,等待下一轮执行console.log('resolved', value)}, function (error) {console.log('rejected', error)})console.log('end')
封装ajax
// Promise 方式的 AJAXfunction ajax (url) {return new Promise(function (resolve, reject) {var xhr = new XMLHttpRequest()xhr.open('GET', url)xhr.responseType = 'json'xhr.onload = function () {if (this.status === 200) {resolve(this.response)} else {reject(new Error(this.statusText))}}xhr.send()})}ajax('/api/urls.json').then(function (res) {console.log(res)}, function (error) {console.log(error)})
链式调用
then方法是promise对象状态明确后的回调,他会返回一个新的promise。
- 如果在then方法中手动返回了一个promise对象,那么下一个then就是这个promise对象状态明确后的回调
- 如果在then方法中手动返回了一个值,这个值会被下一个then当做promise返回的值接收(即便返回的这个值是throw的error也会进入onResolved回调,error成为value)
- 如果在then方法中没有返回,那么下一个then就会收到一个undefined ```javascript // Promise 链式调用
function ajax(url) { return new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest() xhr.open(‘GET’, url) xhr.responseType = ‘json’ xhr.onload = function () { if (this.status === 200) { resolve(this.response) } else { reject(new Error(this.statusText)) } } xhr.send() }) }
// var promise = ajax(‘/api/users.json’)
// var promise2 = promise.then( // function onFulfilled (value) { // console.log(‘onFulfilled’, value) // }, // function onRejected (error) { // console.log(‘onRejected’, error) // } // )
// console.log(promise2 === promise) // false
/ NOTE then方法是promise对象状态明确后的回调,他会返回一个新的promise 如果在then方法中手动返回了一个promise对象,那么下一个then就是这个promise对象状态明确后的回调 如果在then方法中手动返回了一个值,这个值会被下一个then当做promise返回的值接收(即便这个值是throw的error也会进入onResolved回调,error成为value) 如果在then方法中没有返回,那么下一个then就会收到一个undefined / ajax(‘/api/users.json’) .then(function (value) { console.log(1111) console.log(value) return ajax(‘/api/urls.json’) }) // => Promise .then(function (value) { console.log(2222) console.log(value) return ‘foo’ }) // => Promise .then(function (value) { console.log(3333) console.log(value) return new Error(‘error’) }) // => Promise .then(function (value) { console.log(4444) console.log(value) }) // => Promise .then(function (value) { console.log(5555) console.log(value) // return setTimeout(function () { // console.log(‘异步’) // }, 1000) return new Promise((resolve,reject)=>{ setTimeout(function () { console.log(‘异步’) resolve(‘异步’) }, 1000) }) }).then(function (value) { console.log(6666) console.log(value) }).catch(e => { console.log(e) })
/ 1111 [{age: 24,name: “zce”},{age: 25,name: “alan”}] 2222 {users: “/api/users.json”, posts: “/api/posts.json”} 3333 foo 4444 Error: error 5555 undefined /
<a name="r99Zh"></a>## 异常处理<a name="uVfXw"></a>### 使用 onRejected 注册失败回调then中注册的onRejected回调只是给当前 Promise 对象注册的失败回调,只能捕获当前promise的异常<br />then(onRejected) 实际上就相当于 then(undefined, onRejected)```javascriptfunction ajax(url) {return new Promise(function (resolve, reject) {var xhr = new XMLHttpRequest()xhr.open('GET', url)xhr.responseType = 'json'xhr.onload = function () {if (this.status === 200) {resolve(this.response)} else {reject(new Error(this.statusText))}}xhr.send()})}ajax('/api/users11.json').then(function onFulfilled(value) {console.log('onFulfilled', value)}, function onRejected(error) {console.log('onRejected', error)})
使用 catch 注册失败回调
使用 catch 注册失败回调是更常见的(这里的catch并不是try catch中的catch!)
因为 Promise 链条上的任何一个异常都会被一直向后传递,直至被捕获,分开注册的 onRejected 相当于给整个 Promise 链条注册失败回调
function ajax(url) {return new Promise(function (resolve, reject) {var xhr = new XMLHttpRequest()xhr.open('GET', url)xhr.responseType = 'json'xhr.onload = function () {if (this.status === 200) {resolve(this.response)} else {reject(new Error(this.statusText))}}xhr.send()})}// NOTE 使用 catch 注册失败回调是更常见的ajax('/api/users11.json').then(function onFulfilled (value) {console.log('onFulfilled', value)}).catch(function onRejected (error) {console.log('onRejected', error)})
全局捕获 Promise 异常
我们可以在全局对象上注册一个unhandledrejection事件,用来处理那些没有被手动捕获的promise异常
// window 中全局捕获 Promise 异常,类似于 window.onerror,window.addEventListener('unhandledrejection', event => {const { reason, promise } = eventconsole.log(reason, promise)// reason => Promise 失败原因,一般是一个错误对象// promise => 出现异常的 Promise 对象event.preventDefault()}, false)// Node.js 中使用以下方式process.on('unhandledRejection', (reason, promise) => {console.log(reason, promise)// reason => Promise 失败原因,一般是一个错误对象// promise => 出现异常的 Promise 对象})
静态方法
Promise.resolve(‘foo’)
如果传入的是一个普通值,就相当于一个promise成功resolve(‘foo’)
如果传入的是一个 Promise 对象,Promise.resolve 方法原样返回
如果传入的是带有一个跟 Promise 一样的 then 方法的对象,Promise.resolve 会将这个对象作为 Promise 执行
function ajax(url) {return new Promise(function (resolve, reject) {var xhr = new XMLHttpRequest()xhr.open('GET', url)xhr.responseType = 'json'xhr.onload = function () {if (this.status === 200) {resolve(this.response)} else {reject(new Error(this.statusText))}}xhr.send()})}// 如果传入的是一个普通值,就相当于下面写法Promise.resolve('foo').then(function (value) {console.log(value)})new Promise(function (resolve, reject) {resolve('foo')})// 如果传入的是一个 Promise 对象,Promise.resolve 方法原样返回var promise = ajax('/api/users.json')var promise2 = Promise.resolve(promise)console.log(promise === promise2)//true// 如果传入的是带有一个跟 Promise 一样的 then 方法的对象,Promise.resolve 会将这个对象作为 Promise 执行Promise.resolve({then: function (onFulfilled, onRejected) {onFulfilled('foo')}}).then(function (value) {console.log(value)//'foo'})
Promise.reject(‘anything’)
传入任何值,都会作为这个 Promise 失败的理由
// Promise.reject 传入任何值,都会作为这个 Promise 失败的理由Promise.reject(new Error('rejected')).catch(function (error) {console.log(error)})Promise.reject('anything').catch(function (error) {console.log(error)})
并行执行
Promise.all
任何一个出现异常就会进入失败回调
// Promise 并行执行function ajax (url) {return new Promise(function (resolve, reject) {var xhr = new XMLHttpRequest()xhr.open('GET', url)xhr.responseType = 'json'xhr.onload = function () {if (this.status === 200) {resolve(this.response)} else {reject(new Error(this.statusText))}}xhr.send()})}// ajax('/api/users.json')// ajax('/api/posts.json')var promise = Promise.all([ajax('/api/users.json'),ajax('/api/posts1.json')])promise.then(function (values) {console.log(values)}).catch(function (error) {console.log(error)})// 批量发送请求ajax('/api/urls.json').then(value => {const urls = Object.values(value)const tasks = urls.map(url => ajax(url))return Promise.all(tasks)}).then(values => {console.log(values)})
Promise.race
// Promise.race 实现超时控制const request = ajax('/api/posts.json')const timeout = new Promise((resolve, reject) => {setTimeout(() => reject(new Error('timeout')), 500)})Promise.race([request,timeout]).then(value => {console.log(value)}).catch(error => {console.log(error)})
执行时序
Promise 的回调是微任务,本轮调用末尾直接执行
// 微任务console.log('global start')// setTimeout 的回调是 宏任务,进入回调队列排队setTimeout(() => {console.log('setTimeout')}, 0)// Promise 的回调是 微任务,本轮调用末尾直接执行Promise.resolve().then(() => {console.log('promise')}).then(() => {console.log('promise 2')}).then(() => {console.log('promise 3')})console.log('global end')/*global startglobal endpromisepromise 2promise 3setTimeout*/
