第一步:雏形
function Promise(fn) {var value = null,callbacks = []; //callbacks为数组,因为可能同时有很多个回调this.then = function (onFulfilled) {callbacks.push(onFulfilled);};function resolve(value) {callbacks.forEach(function (callback) {callback(value);});}fn(resolve);}let p = new Promise((resolve) => {resolve(1111); // 此处可以改成异步执行函数,例如进行ajax请求}).then((data) => {console.log(data);});
打断点,根据顺序来看
先走fn()函数——>然后理解执行resolve——->然后走源码里面的.then()函数====无打印内容
第二步:使用setTimeOut执行resolve函数
Promises/A+规范明确要求回调需要通过异步方式执行,用以保证一致可靠的执行顺序
function Promise(fn) {var value = null,callbacks = []; //callbacks为数组,因为可能同时有很多个回调this.then = function (onFulfilled) {callbacks.push(onFulfilled);};function resolve(value) {setTimeout(() => {callbacks.forEach(function (callback) {callback(value);});});}fn(resolve);}
做到resolve之前,then函数已经注册回调了
第三步:then函数链式调用
给then函数里面注册回调函数的同时,返回一个新的promise,这样就是链式了
this.then = function (onFulfilled) {callbacks.push(onFulfilled);return this;};
还存在一个问题:如果Promise异步操作已经成功,这时,在异步操作成功之前注册的回调都会执行,但是在Promise异步操作成功这之后调用的then注册的回调就再也不会执行了,也就是永远只执行第一个fn
第四步:加入执行状态
Promises/A+规范中的2.1Promise States中明确规定了,pending可以转化为fulfilled或rejected并且只能转化一次,也就是说如果pending转化到fulfilled状态,那么就不能再转化到rejected。并且fulfilled和rejected状态只能由pending转化而来,两者之间不能互相转换。
function Promise(fn) {var state = 'pending';var value = null;var callbacks = [];this.then = function (onFulfilled) {if (state === 'pending') {callbacks.push(onFulfilled);return this;}onFulfilled(value);return this;};function resolve(newValue) {value = newValue;state = 'fulfilled';setTimeout(function () {callbacks.forEach(function (callback) {callback(value);});}, 0);}fn(resolve);}let p = new Promise((resolve) => {resolve(1111);}).then((data) => {console.log(data);}).then((data) => {console.log(data);});
第五步:连通当前promise和后邻promise
- then函数里面,传了一个回调函数,这个函数被当作参数

- 执行then()方法,会返回一个promise,立即执行,重新走一遍promise构造函数,会先走fn(resolve)方法
- 下面函数就会被执行了

let count = 0;function PromiseFn(fn) {count++;let recordCount = count;let state = 'pending';let value = null;// 执行队列let callbacks = [];this.then = function(onFulfilled) {return new PromiseFn((resolve, reject) => {// 桥梁,将新 Promise 的 resolve 方法,放到前一个 promise 的回调对象中handle({ onFulfilled, resolve });});};function handle(callback) {console.log(recordCount)// 判断如果状态为未完成,则加入到队列中if (state === 'pending') {callbacks.push(callback);return;}if (state === 'fulfilled') {// 如果then中没有回调函数,则结束if (!callback.onFulfilled) {callback.resolve(value);return;}// 处理回调const ret = callback.onFulfilled(value)// 处理下一个 promise 的resolvecallback.resolve(ret)}}function resolve(newValue) {const fn = () => {console.log(state, recordCount, callbacks);if(state !== 'pending') return;state = 'fulfilled';value = newValuehandelCb()}// 基于 PromiseA+ 规范setTimeout(fn, 0)}function handelCb() {while(callbacks.length) {const fulfiledFn = callbacks.shift();handle(fulfiledFn);};}fn(resolve)}// 如果没有添加then函数,则只是运行了一下函数// let p = new PromiseFn(this.test);let p2 = new PromiseFn(this.test).then((data) => {console.log(data)// return 'resolve again'}).then((data) => {console.log(data)});
我们常用的链式调用,是用在异步回调中,以解决”回调地狱”的问题,看如下代码,打印出来的东西跟promise不一样
new Promise((resolve, reject) => {setTimeout(() => {resolve({ test: 1 })}, 1000)}).then((data) => {console.log('result1', data)//dosomethingreturn test()}).then((data) => {console.log('result2', data)})function test(id) {return new Promise(((resolve) => {setTimeout(() => {resolve({ test: 2 })}, 5000)}))}//基于第一个 Promise 模型,执行后的输出//result1 { test: 1 }//result2 Promise {then: ƒ}
需要给resolve函数进行判断,自动执行promise函数
function resolve(newValue){const fn = ()=>{if(state !== 'pending')returnif(newValue && (typeof newValue === 'object' || typeof newValue === 'function')){const {then} = newValueif(typeof then === 'function'){// newValue 为新产生的 Promise,此时resolve为上个 promise 的resolve//相当于调用了新产生 Promise 的then方法,注入了上个 promise 的resolve 为其回调then.call(newValue,resolve)return}}state = 'fulfilled';value = newValuehandelCb()}setTimeout(fn,0)}
