Promise介绍
Promise
理解
抽象表达
- Promise 是 JS 中进行
异步编程
的新解决方案,旧方案是单纯使用回调函数
具体表达
- 从语法上:Promise 是一个
构造函数
- 从功能上:promise 对象用来封装一个
异步操作
并可以获取其成功/失败的结果值
异步编程
- fs 文件操作
require('fs').readFile('./index.html', (err,data)=>{})
|
- 数据库操作
- AJAX
$.get('/server', (data)=>{})
|
- 定时器
setTimeout(()=>{}, 2000);
|
promise 的状态
promise状态:promise实例对象的一个属性,属性名:promiseState,属性是内置的,不能直接对属性进行操作
- promiseState的值有以下三种
- pending 未决定的,初始化的默认值
- resolved / fulfilled 成功
- rejected 失败
promise 的状态改变
- pending 变为
resolved
- pending 变为
rejected
- 说明: 只有这 2 种, 且一个 promise 对象只能
改变一次
- 无论变为成功还是失败, 都会有一个
结果数据
- 成功的结果数据一般称为
value
, 失败的结果数据一般称为 reason
Promise 对象的值
实例对象中的另一个属性 『PromiseResult』
- 保存着异步任务『成功/失败』的结果,resolve和reject可以修改实例对象中的PromiseResult的值
promise 的基本流程
- new promise()创建一个对象,在promise内部封装异步操作
- 如果异步操作成功,则调用resolve()函数,resolve()函数调用将promise对象状态改为成功(fulfilled),成功调then方法时将调用第一参数,即第一个回调函数中的代码,然后返回一个新的promise对象
- 如果异步操作失败,则调用reject()函数,reject()函数调用将promise对象状态改为失败(rejected),失败调then/catch方法时将调用第二参数,即第二个回调函数中的代码,然后返回一个新的promise对象
promise的基本使用
- 实例1
- 点击按钮, 1s 后显示是否中奖(30%概率中奖)
- 若中奖弹出 恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券
- 若未中奖弹出 再接再厉
function rand(m,n){ return Math.ceil(Math.random() * (n-m+1)) + m-1; }
const btn = document.querySelector('#btn');
btn.addEventListener('click', function(){
const p = new Promise((resolve, reject) => { setTimeout(() => { let n = rand(1, 100); if(n <= 30){ resolve(n); }else{ reject(n); } }, 1000); });
console.log(p); p.then((value) => { alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券, 您的中奖数字为 ' + value); }, (reason) => { alert('再接再厉, 您的号码为 ' + reason); });
});
|
util.promisify方法
const util = require('util');
const fs = require('fs');
let mineReadFile = util.promisify(fs.readFile);
mineReadFile('./resource/content.txt').then(value=>{ console.log(value.toString()); });
|
为什么使用Promise
指定回调函数的方式更加灵活
- 旧的: 必须在启动异步任务前指定
- promise: 启动异步任务 => 返回promie对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定多个)
支持链式调用, 可以解决回调地狱问题
function successCallback(result) { console.log("声音文件创建成功: " + result); }
function failureCallback(error) { console.log("声音文件创建失败: " + error); }
createAudioFileAsync(audioSettings, successCallback, failureCallback)
const promise = createAudioFileAsync(audioSettings); setTimeout(() => { promise.then(successCallback, failureCallback); }, 3000);
doSomething(function(result) { doSomethingElse(result, function(newResult) { doThirdThing(newResult, function(finalResult) { console.log('Got the final result: ' + finalResult) }, failureCallback) }, failureCallback) }, failureCallback)
doSomething().then(function(result) { return doSomethingElse(result) }).then(function(newResult) { return doThirdThing(newResult) }).then(function(finalResult) { console.log('Got the final result: ' + finalResult) }).catch(failureCallback)
async function request() { try { const result = await doSomething() const newResult = await doSomethingElse(result) const finalResult = await doThirdThing(newResult) console.log('Got the final result: ' + finalResult) } catch (error) { failureCallback(error) } }
|
如何使用 Promise?
API
- Promise 构造函数: Promise (excutor) {}
- (1) executor 函数: 执行器 (resolve, reject) => {}/匿名函数,executor 函数中有两个形参resolve, reject
- (2) resolve 函数: 内部定义成功时调用的函数 value => {}
- (3) reject 函数: 内部定义失败时调用的函数 reason => {}
说明: executor 会在 Promise 内部立即同步调用,异步操作在执行器中执行
let p = new Promise((resolve, reject) => { console.log(222) }); console.log(111)
222 111
|
- Promise.prototype.then 方法: (onResolved, onRejected) => {}
- (1) onResolved 函数: 成功的回调函数 (value) => {}
- (2) onRejected 函数: 失败的回调函数 (reason) => {}
说明: 指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调,返回一个新的 promise 对象
- Promise.prototype.catch 方法: (onRejected) => {}
- (1) onRejected 函数: 失败的回调函数 (reason) => {}
说明: then()的语法糖, 相当于: then(undefined, onRejected)
let p = new Promise((resolve, reject) => { reject('error') });
p.catch(reason => { console.log(reason) })
|
- Promise.resolve 方法: (value) => {}
- (1) value: 成功的数据或 promise 对象
说明: 返回一个成功/失败的 promise 对象
let p1 = Promise.resolve(521);
let p2 = Promise.resolve(new Promise((resolve, reject) => { reject('Error'); })); console.log(p2); p2.catch(reason => { console.log(reason); })
|
- Promise.reject 方法: (reason) => {}
- (1) reason: 失败的原因
说明: 返回一个失败的 promise 对象
let p = Promise.reject(521); let p2 = Promise.reject('iloveyou'); let p3 = Promise.reject(new Promise((resolve, reject) => { resolve('OK'); }));
console.log(p3); p3.catch(reason => { console.log(reason); reason.then(res => { console.log(res); }) })
|
- Promise.all 方法: (promises) => {}
- (1) promises: 包含 n 个 promise 的数组
- 成功结果:每一个promise对象成功结果组成的数组
- 失败结果:在数组中第一个失败的promise对象失败的结果
说明: 返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就直接失败
let p1 = new Promise((resolve, reject) => { resolve('OK'); }) let p2 = Promise.reject('Error1'); let p3 = Promise.resolve('Success'); let p4 = Promise.resolve('Oh Yeah'); let p5 = Promise.resolve('Error2'); const result = Promise.all([p1, p3, p4]); console.log(result);
const result1 = Promise.all([p1, p2, p5]); console.log(result1)
const result2 = Promise.all([p1, p5, p2]); console.log(result2)
|
- Promise.race 方法: (promises) => {}
- (1) promises: 包含 n 个 promise 的数组
说明: 返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态
let p1 = new Promise((resolve, reject) => { resolve('OK'); }) let p2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('OK'); }, 1000); }) let p3 = Promise.resolve('Success'); let p4 = Promise.resolve('Oh Yeah');
const result = Promise.race([p1, p3, p4]); console.log(result);
const result1 = Promise.race([p2, p3, p4]); console.log(result1);
|
promise 的几个关键问题
- 如何改变 promise 的状态?
- (1)
resolve(value)
: 如果当前是 pending 就会变为 resolved
- (2)
reject(reason)
: 如果当前是 pending 就会变为 rejected
- (3)
抛出异常
: 如果当前是 pending 就会变为 rejected
let p = new Promise((resolve, reject) => { });
|
- 一个 promise 指定
多个成功/失败
回调函数, 都会调用吗?
let p = new Promise((resolve, reject) => { resolve('OK'); });
p.then(value => { console.log(value); });
p.then(value => { console.log(222); });
OK 222
|
- 改变 promise 状态和指定回调函数谁先谁后?
- (1) 都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
- (2) 如何先改状态再指定回调?
- ① 在执行器中直接调用 resolve()/reject()
- ② 延迟更长时间才调用 then()
- (3) 什么时候才能得到数据?
- ① 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
- ② 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
let p = new Promise((resolve, reject) => { setTimeout(() => { resolve('OK'); }, 1000); });
p.then(value => { console.log(value); },reason=>{
})
|
- promise.then()返回的新 promise 的结果状态由什么决定?
- (1) 简单表达: 由 then()指定的回调函数执行的结果决定
- (2) 详细表达:
- ① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
- ② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
- ③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果
let p = new Promise((resolve, reject) => { resolve('ok'); });
let result = p.then(value => { return new Promise((resolve, reject) => { reject('error'); }); }, reason => { console.warn(reason); });
console.log(result);
|
- promise 如何串连多个操作任务?
- (1) promise 的 then()返回一个新的 promise, 可以形成 then()的链式调用
- (2) 通过 then 的链式调用串连多个同步/异步任务
let p = new Promise((resolve, reject) => { setTimeout(() => { resolve('OK'); }, 1000); });
p.then(value => { return new Promise((resolve, reject) => { resolve("success"); }); }).then(value => { console.log(value); }).then(value => { console.log(value); })
|
- promise 异常传透?
- (1) 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调,
- (2) 前面任何操作出了异常, 都会传到最后失败的回调中处理
let p = new Promise((resolve, reject) => { setTimeout(() => { resolve('OK'); }, 1000); });
p.then(value => { throw '失败啦!'; }).then(value => { console.log(222); }).then(value => { console.log(333); }).catch(reason => { console.warn(reason); });
|
- 中断 promise 链?
- (1) 当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
- (2) 办法: 在回调函数中返回一个 pending 状态的 promise 对象,因为状态没有改变
let p = new Promise((resolve, reject) => { setTimeout(() => { resolve('OK'); }, 1000); });
p.then(value => { console.log(111); return new Promise(() => {}); }).then(value => { console.log(222); }).then(value => { console.log(333); }).catch(reason => { console.warn(reason); });
111
|
Promise 自定义封装
初始化结构搭建
function Promise(executor){
}
Promise.prototype.then = function(onResolved, onRejected){
}
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 1 - 初始结构搭建</title> <script src="./promise.js"></script> </head> <body> <script> let p = new Promise((resolve, reject) => { resolve('OK'); });
p.then(value => { console.log(value); }, reason=>{ console.warn(reason); }) </script> </body> </html>
|
resolve与reject结构搭建
function Promise(executor){ function resolve(data){
} function reject(data){
}
executor(resolve, reject); }
Promise.prototype.then = function(onResolved, onRejected){
}
|
resolve与reject函数实现
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; const self = this; function resolve(data){ self.PromiseState = 'fulfilled'; self.PromiseResult = data; } function reject(data){ self.PromiseState = 'rejected'; self.PromiseResult = data; }
executor(resolve, reject); }
Promise.prototype.then = function(onResolved, onRejected){
}
|
throw抛出错误改变状态
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; const self = this; function resolve(data){ self.PromiseState = 'fulfilled'; self.PromiseResult = data; } function reject(data){ self.PromiseState = 'rejected'; self.PromiseResult = data; } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){
}
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 4 - throw 抛出异常改变状态 </title> </head> <body> <script> let p = new Promise((resolve, reject) => { throw "error"; });
console.log(p); </script> </body> </html>
|
状态只能修改一次
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){
}
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 5 - 状态只能修改一次 </title> <script src="./promise.js"></script> </head> <body> <script> let p = new Promise((resolve, reject) => { reject("error"); resolve('OK'); });
console.log(p); </script> </body> </html>
|
then方法执行回调
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){ if(this.PromiseState === 'fulfilled'){ onResolved(this.PromiseResult); } if(this.PromiseState === 'rejected'){ onRejected(this.PromiseResult); } }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 6 - then 方法执行回调 </title> <script src="./promise.js"></script> </head> <body> <script> let p = new Promise((resolve, reject) => { throw "ERROR"; });
p.then(value => { console.log(value); }, reason=>{ console.warn(reason); }) </script> </body> </html>
|
异步任务then方法执行回调
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; this.callback = {}; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; if(self.callback.onResolved){ self.callback.onResolved(data); } } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; if(self.callback.onResolved){ self.callback.onResolved(data); } } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){ if(this.PromiseState === 'fulfilled'){ onResolved(this.PromiseResult); } if(this.PromiseState === 'rejected'){ onRejected(this.PromiseResult); } if(this.PromiseState === 'pending'){ this.callback = { onResolved: onResolved, onRejected: onRejected } } }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 7 - 异步任务 then 方法实现 </title> <script src="./promise.js"></script> </head> <body> <script> let p = new Promise((resolve, reject) => { setTimeout(() => { reject("error"); }, 1000); });
p.then(value => { console.log(value); }, reason=>{ console.warn(reason); });
console.log(p); </script> </body> </html>
|
指定多个回调
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; this.callbacks = []; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onResolved(data); }); } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onRejected(data); }); } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){ if(this.PromiseState === 'fulfilled'){ onResolved(this.PromiseResult); } if(this.PromiseState === 'rejected'){ onRejected(this.PromiseResult); } if(this.PromiseState === 'pending'){ this.callbacks.push({ onResolved: onResolved, onRejected: onRejected }); } }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 8 - 指定多个回调 </title> <script src="./promise.js"></script> </head> <body> <script> let p = new Promise((resolve, reject) => { setTimeout(() => { reject('No'); }, 1000); });
p.then(value => { console.log(value); }, reason=>{ console.warn(reason); });
p.then(value => { alert(value); }, reason=>{ alert(reason); });
console.log(p); </script> </body> </html>
|
同步修改状态then方法返回结果
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; this.callbacks = []; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onResolved(data); }); } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onRejected(data); }); } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){ return new Promise((resolve, reject) => { if(this.PromiseState === 'fulfilled'){ try{ let result = onResolved(this.PromiseResult); if(result instanceof Promise){ result.then(v => { resolve(v); }, r=>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } if(this.PromiseState === 'rejected'){ onRejected(this.PromiseResult); } if(this.PromiseState === 'pending'){ this.callbacks.push({ onResolved: onResolved, onRejected: onRejected }); } }) }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 9 - 同步任务 then 返回结果</title> <script src="./promise.js"></script> </head> <body> <script> let p = new Promise((resolve, reject) => { resolve('OK'); }); const res = p.then(value => {
throw "FAIL"; }, reason=>{ console.warn(reason); }); console.log(res); </script> </body> </html>
|
异步修改状态then方法返回结果
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; this.callbacks = []; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onResolved(data); }); } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onRejected(data); }); } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){ const self = this; return new Promise((resolve, reject) => { if(this.PromiseState === 'fulfilled'){ try{ let result = onResolved(this.PromiseResult); if(result instanceof Promise){ result.then(v => { resolve(v); }, r=>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } if(this.PromiseState === 'rejected'){ onRejected(this.PromiseResult); } if(this.PromiseState === 'pending'){ this.callbacks.push({ onResolved: function(){ try{ let result = onResolved(self.PromiseResult); if(result instanceof Promise){ result.then(v => { resolve(v); }, r=>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } }, onRejected: function(){ try{ let result = onRejected(self.PromiseResult); if(result instanceof Promise){ result.then(v => { resolve(v); }, r=>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } }); } }) }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 10 - 异步任务 then 返回结果</title> <script src="./promise.js"></script> </head> <body> <script> let p = new Promise((resolve, reject) => { setTimeout(() => { reject("Error"); }, 1000) });
const res = p.then(value => { throw 'error'; }, reason=>{ throw 'error'; });
console.log(res); </script> </body> </html>
|
then方法代码优化
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; this.callbacks = []; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onResolved(data); }); } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onRejected(data); }); } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){ const self = this; return new Promise((resolve, reject) => { function callback(type){ try{ let result = type(self.PromiseResult); if(result instanceof Promise){ result.then(v => { resolve(v); }, r=>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } if(this.PromiseState === 'fulfilled'){ callback(onResolved); } if(this.PromiseState === 'rejected'){ callback(onRejected); } if(this.PromiseState === 'pending'){ this.callbacks.push({ onResolved: function(){ callback(onResolved); }, onRejected: function(){ callback(onRejected); } }); } }) }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 10 - 异步任务 then 返回结果</title> <script src="./promise.js"></script> </head> <body> <script> let p = new Promise((resolve, reject) => { setTimeout(() => { reject("Error"); }, 1000) });
const res = p.then(value => { throw 'error'; }, reason=>{ throw 'error'; });
console.log(res); </script> </body> </html>
|
catch方法与异常穿透
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; this.callbacks = []; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onResolved(data); }); } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onRejected(data); }); } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){ const self = this; if(typeof onRejected !== 'function'){ onRejected = reason => { throw reason; } } if(typeof onResolved !== 'function'){ onResolved = value => value; } return new Promise((resolve, reject) => { function callback(type){ try{ let result = type(self.PromiseResult); if(result instanceof Promise){ result.then(v => { resolve(v); }, r=>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } if(this.PromiseState === 'fulfilled'){ callback(onResolved); } if(this.PromiseState === 'rejected'){ callback(onRejected); } if(this.PromiseState === 'pending'){ this.callbacks.push({ onResolved: function(){ callback(onResolved); }, onRejected: function(){ callback(onRejected); } }); } }) }
Promise.prototype.catch = function(onRejected){ return this.then(undefined, onRejected); }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 11 - catch 方法与异常穿透</title> <script src="./promise.js"></script> </head> <body> <script> let p = new Promise((resolve, reject) => { setTimeout(() => { resolve('OK'); }, 1000); });
p.then(value=>{ console.log(222); throw 'error' }).then(value => { console.log(333); }).catch(reason => { console.warn(reason); });
p.then().then(value => { console.log(333); }).catch(reason => { console.warn(reason); });
</script> </body> </html>
|
Promise.resolve 和 Promise.reject 封装
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; this.callbacks = []; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onResolved(data); }); } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onRejected(data); }); } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){ const self = this; if(typeof onRejected !== 'function'){ onRejected = reason => { throw reason; } } if(typeof onResolved !== 'function'){ onResolved = value => value; } return new Promise((resolve, reject) => { function callback(type){ try{ let result = type(self.PromiseResult); if(result instanceof Promise){ result.then(v => { resolve(v); }, r=>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } if(this.PromiseState === 'fulfilled'){ callback(onResolved); } if(this.PromiseState === 'rejected'){ callback(onRejected); } if(this.PromiseState === 'pending'){ this.callbacks.push({ onResolved: function(){ callback(onResolved); }, onRejected: function(){ callback(onRejected); } }); } }) }
Promise.prototype.catch = function(onRejected){ return this.then(undefined, onRejected); }
Promise.resolve = function(value){ return new Promise((resolve, reject) => { if(value instanceof Promise){ value.then(v=>{ resolve(v); }, r=>{ reject(r); }) }else{ resolve(value); } }); }
Promise.reject = function(reason){ return new Promise((resolve, reject)=>{ reject(reason); }); }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 12 - Promise.resolve 封装</title> <script src="./promise.js"></script> </head> <body> <script> const p = Promise.resolve('OK'); const p2 = Promise.resolve(new Promise((resolve, reject) => { reject("error"); })); const p3 = Promise.resolve(Promise.resolve('Oh Yeah'));
console.log(p3);
const p4 = Promise.reject('Error'); const p5 = Promise.reject(new Promise((resolve, reject) => { resolve('OK'); }));
console.log(p4); console.log(p5); </script> </body> </html>
|
Promise.all 方法实现
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; this.callbacks = []; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onResolved(data); }); } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onRejected(data); }); } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){ const self = this; if(typeof onRejected !== 'function'){ onRejected = reason => { throw reason; } } if(typeof onResolved !== 'function'){ onResolved = value => value; } return new Promise((resolve, reject) => { function callback(type){ try{ let result = type(self.PromiseResult); if(result instanceof Promise){ result.then(v => { resolve(v); }, r=>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } if(this.PromiseState === 'fulfilled'){ callback(onResolved); } if(this.PromiseState === 'rejected'){ callback(onRejected); } if(this.PromiseState === 'pending'){ this.callbacks.push({ onResolved: function(){ callback(onResolved); }, onRejected: function(){ callback(onRejected); } }); } }) }
Promise.prototype.catch = function(onRejected){ return this.then(undefined, onRejected); }
Promise.resolve = function(value){ return new Promise((resolve, reject) => { if(value instanceof Promise){ value.then(v=>{ resolve(v); }, r=>{ reject(r); }) }else{ resolve(value); } }); }
Promise.reject = function(reason){ return new Promise((resolve, reject)=>{ reject(reason); }); }
Promise.all = function(promises){ return new Promise((resolve, reject) => { let count = 0; let arr = []; for(let i=0;i<promises.length;i++){ promises[i].then(v => { count++; arr[i] = v; if(count === promises.length){ resolve(arr); } }, r => { reject(r); }); } }); }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 14 - Promise.all 封装</title> <script src="./promise.js"></script> </head> <body> <script> let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('OK'); }, 1000) }) let p2 = Promise.reject('Success'); let p3 = Promise.resolve('Oh Yeah');
let result = Promise.all([p1, p2, p3]);
console.log(result); </script> </body> </html>
|
Promise.race 方法实现
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; this.callbacks = []; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onResolved(data); }); } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; self.callbacks.forEach(item => { item.onRejected(data); }); } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){ const self = this; if(typeof onRejected !== 'function'){ onRejected = reason => { throw reason; } } if(typeof onResolved !== 'function'){ onResolved = value => value; } return new Promise((resolve, reject) => { function callback(type){ try{ let result = type(self.PromiseResult); if(result instanceof Promise){ result.then(v => { resolve(v); }, r=>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } if(this.PromiseState === 'fulfilled'){ callback(onResolved); } if(this.PromiseState === 'rejected'){ callback(onRejected); } if(this.PromiseState === 'pending'){ this.callbacks.push({ onResolved: function(){ callback(onResolved); }, onRejected: function(){ callback(onRejected); } }); } }) }
Promise.prototype.catch = function(onRejected){ return this.then(undefined, onRejected); }
Promise.resolve = function(value){ return new Promise((resolve, reject) => { if(value instanceof Promise){ value.then(v=>{ resolve(v); }, r=>{ reject(r); }) }else{ resolve(value); } }); }
Promise.reject = function(reason){ return new Promise((resolve, reject)=>{ reject(reason); }); }
Promise.all = function(promises){ return new Promise((resolve, reject) => { let count = 0; let arr = []; for(let i=0;i<promises.length;i++){ promises[i].then(v => { count++; arr[i] = v; if(count === promises.length){ resolve(arr); } }, r => { reject(r); }); } }); }
Promise.race = function(promises){ return new Promise((resolve, reject) => { for(let i=0;i<promises.length;i++){ promises[i].then(v => { resolve(v); },r=>{ reject(r); }) } }); }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 15 - Promise.race 封装</title> <script src="./promise.js"></script> </head> <body> <script> let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('OK'); }); }); let p2 = Promise.reject('Success'); let p3 = Promise.resolve('Oh Yeah');
let result = Promise.race([p1, p2, p3]);
console.log(result); </script> </body> </html>
|
then回调函数异步执行的实现
function Promise(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; this.callbacks = []; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; setTimeout(() => { self.callbacks.forEach(item => { item.onResolved(data); }); }); } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; setTimeout(() => { self.callbacks.forEach(item => { item.onRejected(data); }); }); } try{ executor(resolve, reject); }catch(e){ reject(e); } }
Promise.prototype.then = function(onResolved, onRejected){ const self = this; if(typeof onRejected !== 'function'){ onRejected = reason => { throw reason; } } if(typeof onResolved !== 'function'){ onResolved = value => value; } return new Promise((resolve, reject) => { function callback(type){ try{ let result = type(self.PromiseResult); if(result instanceof Promise){ result.then(v => { resolve(v); }, r=>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } if(this.PromiseState === 'fulfilled'){ setTimeout(() => { callback(onResolved); }) } if(this.PromiseState === 'rejected'){ setTimeout(() => { callback(onRejected); }); } if(this.PromiseState === 'pending'){ this.callbacks.push({ onResolved: function(){ callback(onResolved); }, onRejected: function(){ callback(onRejected); } }); } }) }
Promise.prototype.catch = function(onRejected){ return this.then(undefined, onRejected); }
Promise.resolve = function(value){ return new Promise((resolve, reject) => { if(value instanceof Promise){ value.then(v=>{ resolve(v); }, r=>{ reject(r); }) }else{ resolve(value); } }); }
Promise.reject = function(reason){ return new Promise((resolve, reject)=>{ reject(reason); }); }
Promise.all = function(promises){ return new Promise((resolve, reject) => { let count = 0; let arr = []; for(let i=0;i<promises.length;i++){ promises[i].then(v => { count++; arr[i] = v; if(count === promises.length){ resolve(arr); } }, r => { reject(r); }); } }); }
Promise.race = function(promises){ return new Promise((resolve, reject) => { for(let i=0;i<promises.length;i++){ promises[i].then(v => { resolve(v); },r=>{ reject(r); }) } }); }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 16 - 回调函数『异步执行』</title> <script src="./promise.js"></script> </head> <body> <script> let p1 = new Promise((resolve, reject) => { reject('OK'); console.log(111); }); p1.then(value => { console.log(222); }, reason => { console.log(444); });
console.log(333); </script> </body> </html>
// 执行结果 111 333 444
|
class版本封装
class Promise{ constructor(executor){ this.PromiseState = 'pending'; this.PromiseResult = null; this.callbacks = []; const self = this; function resolve(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'fulfilled'; self.PromiseResult = data; setTimeout(() => { self.callbacks.forEach(item => { item.onResolved(data); }); }); } function reject(data){ if(self.PromiseState !== 'pending') return; self.PromiseState = 'rejected'; self.PromiseResult = data; setTimeout(() => { self.callbacks.forEach(item => { item.onRejected(data); }); }); } try{ executor(resolve, reject); }catch(e){ reject(e); } }
then(onResolved,onRejected){ const self = this; if(typeof onRejected !== 'function'){ onRejected = reason => { throw reason; } } if(typeof onResolved !== 'function'){ onResolved = value => value; } return new Promise((resolve, reject) => { function callback(type){ try{ let result = type(self.PromiseResult); if(result instanceof Promise){ result.then(v => { resolve(v); }, r=>{ reject(r); }) }else{ resolve(result); } }catch(e){ reject(e); } } if(this.PromiseState === 'fulfilled'){ setTimeout(() => { callback(onResolved); }); } if(this.PromiseState === 'rejected'){ setTimeout(() => { callback(onRejected); }); } if(this.PromiseState === 'pending'){ this.callbacks.push({ onResolved: function(){ callback(onResolved); }, onRejected: function(){ callback(onRejected); } }); } }) }
catch(onRejected){ return this.then(undefined, onRejected); }
static resolve(value){ return new Promise((resolve, reject) => { if(value instanceof Promise){ value.then(v=>{ resolve(v); }, r=>{ reject(r); }) }else{ resolve(value); } }); }
static reject(reason){ return new Promise((resolve, reject)=>{ reject(reason); }); }
static all(promises){ return new Promise((resolve, reject) => { let count = 0; let arr = []; for(let i=0;i<promises.length;i++){ promises[i].then(v => { count++; arr[i] = v; if(count === promises.length){ resolve(arr); } }, r => { reject(r); }); } }); }
static race(promises){ return new Promise((resolve, reject) => { for(let i=0;i<promises.length;i++){ promises[i].then(v => { resolve(v); },r=>{ reject(r); }) } }); } }
|
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise-封装 | 17 - class版本封装</title> <script src="./promise.js"></script> </head> <body> <script> let p1 = new Promise((resolve, reject) => { setTimeout(() => { reject("Error"); }) });
p1.then(value => { console.log(value); }, reason => { console.warn(reason); });
console.log(Promise.resolve('OK')); </script> </body> </html>
|
async 与 await
文档
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_function
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/await
async 函数
- 函数的返回值为
promise 对象
promise 对象
的结果
由 async 函数执行的返回值
决定
async function main(){ throw "Oh NO"; }
let result = main();
console.log(result);
|
await 表达式
- await 右侧的表达式一般为
promise 对象
, 但也可以是其它的值
- 如果表达式是
promise 对象
, await 返回的是 promise 成功的值
- 如果表达式是
其它值
, 直接将此值作为 await 的返回值
注意
await
必须写在 async 函数
中, 但 async 函数
中可以没有 await
- 如果
await
的 promise 失败
了, 就会抛出异常
, 需要通过 try...catch
捕获处理
async function main(){ let p = new Promise((resolve, reject) => { reject('Error'); }) try{ let res3 = await p; }catch(e){ console.log(e); } }
main();
|
async与await结合
const fs = require('fs'); const util = require('util'); const mineReadFile = util.promisify(fs.readFile);
async function main(){ try{ let data1 = await mineReadFile('./resource/1x.html'); let data2 = await mineReadFile('./resource/2.html'); let data3 = await mineReadFile('./resource/3.html'); console.log(data1 + data2 + data3); }catch(e){ console.log(e); } }
main();
|
async与await结合发送AJAX
function sendAJAX(url){ return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.responseType = 'json'; xhr.open("GET", url); xhr.send(); xhr.onreadystatechange = function(){ if(xhr.readyState === 4){ if(xhr.status >= 200 && xhr.status < 300){ resolve(xhr.response); }else{ reject(xhr.status); } } } }); }
let btn = document.querySelector('#btn');
btn.addEventListener('click',async function(){ let duanzi = await sendAJAX('https://api.apiopen.top/getJoke'); console.log(duanzi); });
|