文 / 景朝霞
来源公号 / 朝霞的光影笔记
ID / zhaoxiajingjing
❥❥❥❥点个赞,让我知道你来过~❥❥❥❥
Promise 能够解决的问题javascript
// 此处使用node举例,不会没关系,先混个脸熟。再见就不陌生了呀 let fs = require('fs'); // 异步读取文件 fs.readFile('./name', function (err, data){ if(err){} fs.readFile(data, function (err, address){ if(err){} fs.readFile(address, function (err, product){ // 1)深陷在回调地域中不能抽身 if(err){ // 2)捕获错误。OMG,我哪里错了?!?!告诉我,确定改~ } }); }); }); // 3) 你的名字、你的地址。都告诉我,惊喜才会送到你面前呀~ fs.readFile('./name', function (err, data){}); fs.readFile('./address', function (err, data){});
- pending 等待态
- fulfilled 成功态
- rejected 失败态
【等待态 -> 成功态】 or 【等待态 -> 失败态】二选一,你来定。java
console.log('一封情书'); let p = new Promise((resolve, reject)=>{ console.log('executor请说出你的选择:'); resolve('你中意我~(*^▽^*)'); reject('你发了好人卡(╥﹏╥)o'); }); p.then((value)=>{ console.log('成功态', value); }, (reason) => { console.log('失败态', reason); }); console.log('纸短情长');
console.log('-----一封情书-----'); let p = new Promise((resolve, reject) => { console.log('executor 请说出你的选择:'); resolve('你中意我~(*^▽^*)'); reject('你发了好人卡(╥﹏╥)o'); }); p.then((value) => { console.log('成功态---', value); }, (reason) => { console.log('失败态---', reason); }).then((value) => { console.log('---爱你一万年~(*^▽^*)'); }, (reason) => { console.log('---伤心老是不免的o(╥﹏╥)o'); }); console.log('~~~纸短情长~~~');
zhaoxiajingjing
let fs = require('fs'); let p = new Promise((resolve, reject)=>{ fs.readFile('./name.txt', 'utf8', function (err, data){ if(err){ return reject(err); } resolve(data); }); }); p.then((value)=>{ console.log('成功了', value); }, (reason)=>{ console.log('失败了', reason); });
下面的例子输出什么呢?node
let fs = require('fs'); function read(filePath) { return new Promise((resolve, reject) => { fs.readFile(filePath, 'utf8',function(err, data){ if(err) { return reject(err); } resolve(data); }); }); } read('./name.txt') // then-1 .then(function (data) { console.log('data①', data); return new Promise((resolve, reject) => { reject('错误了'); }); }) // then-2 .then((data) => { console.log('data②', data); }, err => { console.log('err②', err); }) // then-3 .then((data) => { console.log('data③', data); }, (err) => { console.log('err③', err); });
OK,提炼一下重点: git
代码1,传送门~es6
const PENDING = 'pending'; const SUCCESS = 'fulfilled'; const FAIL = 'rejected'; class Promise{ constructor(execuotr){ const status = PENDING; // 我等着你给答案~ this.value; this.reason; let resolve = (value)=>{ if(status === PENDING) { this.status = SUCCESS; // 你中意我~ this.value = value; } }; let reject = (reason)=>{ if(status === PENDING) { this.status = FAIL; // 你发了好人卡 this.reason = reason; } }; // 是同步的哦~ try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected){ if(this.status === SUCCESS) { onFulfilled(this.value); // 爱你一万年~ } if(this.status === FAIL) { onRejected(this.reason); // 伤心老是不免的 } } }
Promise 是个容器,里面能够放一些异步的请求,请求成功了走成功态,请求失败了走失败态。固然,你要反过来走也能够哒~github
代码2,传送门~npm
const PENDING = 'pending'; const SUCCESS = 'fulfilled'; const FAIL = 'rejected'; class Promise { constructor(executor){ this.status = PENDING; this.value; this.reason; // 用来存储 订阅的内容的 this.onSuccessCallbacks = []; this.onFailCallbacks = []; let resolve = (value)=>{ if(this.status === PENDING) { this.status = SUCCESS; this.value = value; this.onSuccessCallbacks.forEach(fn => fn()); } }; let reject = (reason)=>{ if(this.status === PENDING) { this.status = FAIL; this.reason = reason; this.onFailCallbacks.forEach(fn => fn()); } }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected){ if(this.status === SUCCESS){ onFulfilled(this.value); } if(this.status === FAIL){ onRejected(this.reason); } // 当Promise里面有异步请求控制状态改变时,会先走到then方法里面 if(this.status === PENDING) { this.onSuccessCallbacks.push(()=>{ onFulfilled(this.value); }); this.onFailCallbacks.push(()=>{ onRejected(this.reason); }); } } }
Promise 里面有异步请求时候,会先走到 then方法里面了。此时,须要把成功态回调和失败态回调先存储起来,等到异步请求回来之后变动了状态,再触发执行。promise
Promise 一辈子只能改变一次状态。那么,Promise 的链式调用then方法,说明每次都会返回一个新的Promise。浏览器
代码3,传送门~并发
const SUCCESS = 'fulfilled'; const FAIL = 'rejected'; const PENDING = 'pending'; class Promise { constructor(executor) { // ... executor 代码 } then(onFulfilled, onRejected) { let promise2; promise2 = new Promise((resolve, reject)=>{ if (this.status === SUCCESS) { try { // 用 try catch 捕获同步的报错 // 成功态的回调的返回值 x // 【问题】 若是 x 是一个promise,那么须要取得x执行后的结果 let x = onFulfilled(this.value); resolve(x); } catch (e) { reject(e); } } if (this.status === FAIL) { try { let x = onRejected(this.reason); resolve(x); } catch (e) { reject(e); } } if (this.status === PENDING) { this.onSuccessCallbacks.push(()=>{ try { let x = onFulfilled(this.value); resolve(x); } catch (e) { reject(e); } }); this.onFailCallbacks.push(()=>{ try { let x = onRejected(this.reason); resolve(x); } catch (e) { reject(e); } }); } }); return promise2; } }
如何判断 x 是Promise,仍是一个普通值?【参考规范 https://promisesaplus.com "Promise A+" 2.2.7】
const SUCCESS = 'fulfilled'; const FAIL = 'rejected'; const PENDING = 'pending'; function resolvePromise(promise2, x, resolve, reject) { // 死循环了,容错 if(promise2 === x) { return reject('TypeError: Chaining cycle detected for promise~~~~'); } // 判断 x 类型 if(typeof x === 'function' || (typeof x === 'object' && x != null)) { // 这个才有多是 promise try { let then = x.then; if(typeof then === 'function') { // 此时,认为就是个promise // 若是promise是成功的,那么结果向下传递,若是失败了就传到下一个失败里面去 then.call(x, y=>{ resolvePromise(promise2, y, resolve, reject); }, r => { reject(r); }); } else { resolve(x); } } catch (e) { reject(e); } } else { // x 确定不是一个promise resolve(x); } } class Promise { constructor(executor) { // ... executor 代码 } then(onFulfilled, onRejected) { let promise2; promise2 = new Promise((resolve, reject) => { if (this.status === SUCCESS) { // 用定时器模拟此时promise2已经能获取到了 setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); } // 其余状况同理,先以一个为例说明 }); return promise2; } }
Promise 给你的承诺,一句情话:一个 Promise 一辈子只改变一次状态
const SUCCESS = 'fulfilled'; const FAIL = 'rejected'; const PENDING = 'pending'; function resolvePromise(promise2, x, resolve, reject) { // 死循环了,容错 if(promise2 === x) { return reject('TypeError: Chaining cycle detected for promise~~~~'); } let called; if(typeof x === 'function' || (typeof x === 'object' && x != null)) { try { let then = x.then; if(typeof then === 'function') { then.call(x, y=>{ if(called) return; called = true; resolvePromise(promise2, y, resolve, reject); }, r => { if(called) return; called = true; reject(r); }); } else { resolve(x); } } catch (e) { if(called) return; called = true; reject(e); } } else { resolve(x); } } class Promise { constructor(executor) { // .... executor 的代码 } then(onFulfilled, onRejected) { let promise2; promise2 = new Promise((resolve, reject) => { if (this.status === SUCCESS) { // 用定时器模拟此时promise2已经能获取到了 setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); } // 其余状况同理,先以一个为例说明 }); return promise2; } }
let p = new Promise((resolve, reject)=>{ resolve(1000); }); p.then().then().then(data => { console.log(data); });
值能够传过去
const SUCCESS = 'fulfilled'; const FAIL = 'rejected'; const PENDING = 'pending'; function resolvePromise(promise2, x, resolve, reject) { // ... 判断 x 的值 } class Promise { constructor(executor) { // ... executor 代码 } then(onFulfilled, onRejected) { // 值穿透 onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val; onRejected = typeof onRejected === 'function' ? onRejected : err => {throw err}; // ... promise2 的判断 } }
promises-aplus-tests
用来测试当前的库是否符合规范npm i promises-aplus-tests -g
promises-aplus-tests 文件名
Promise 是一个构造函数,是个类。默认高版本浏览器,node都自带了。不用考虑兼容性,放心大胆的使用吧!若是真不兼容,那就用es6-promise包本身是一套吧~
Promise A+
上面的内容,还须要一部分容错。就是当executor 里面的有一个promise的时候,执行的结果。
let Promise = require('./promise.js'); let p = new Promise((resolve, reject)=>{ resolve(new Promise((resolve, reject)=>{ reject(404); })); }); p.then(value => console.log(1, value), reason => console.log(2, reason)); // 输出: // 2 404
在同步执行时,resolve 的value是一个Promise,那么须要等它的结果。
const SUCCESS = 'fulfilled'; const FAIL = 'rejected'; const PENDING = 'pending'; function resolvePromise(promise2, x, resolve, reject) { // ... 校验x } class Promise { constructor(executor) { // ... code let resolve = (value) => { if (value instanceof Promise) { return value.then(resolve, reject); } if (this.status === PENDING) { this.status = SUCCESS; this.value = value; this.onSuccessCallbacks.forEach(fn => fn()); } }; // ... code } then(onFulfilled, onRejected) { // ... then 方法 } } module.exports = Promise;
在这里,一块儿成长~