第一步:雏形

  1. function Promise(fn) {
  2. var value = null,
  3. callbacks = []; //callbacks为数组,因为可能同时有很多个回调
  4. this.then = function (onFulfilled) {
  5. callbacks.push(onFulfilled);
  6. };
  7. function resolve(value) {
  8. callbacks.forEach(function (callback) {
  9. callback(value);
  10. });
  11. }
  12. fn(resolve);
  13. }
  14. let p = new Promise((resolve) => {
  15. resolve(1111); // 此处可以改成异步执行函数,例如进行ajax请求
  16. }).then((data) => {
  17. console.log(data);
  18. });

打断点,根据顺序来看
先走fn()函数——>然后理解执行resolve——->然后走源码里面的.then()函数====无打印内容

第二步:使用setTimeOut执行resolve函数

Promises/A+规范明确要求回调需要通过异步方式执行,用以保证一致可靠的执行顺序

  1. function Promise(fn) {
  2. var value = null,
  3. callbacks = []; //callbacks为数组,因为可能同时有很多个回调
  4. this.then = function (onFulfilled) {
  5. callbacks.push(onFulfilled);
  6. };
  7. function resolve(value) {
  8. setTimeout(() => {
  9. callbacks.forEach(function (callback) {
  10. callback(value);
  11. });
  12. });
  13. }
  14. fn(resolve);
  15. }

做到resolve之前,then函数已经注册回调了

第三步:then函数链式调用

给then函数里面注册回调函数的同时,返回一个新的promise,这样就是链式了

  1. this.then = function (onFulfilled) {
  2. callbacks.push(onFulfilled);
  3. return this;
  4. };

还存在一个问题:如果Promise异步操作已经成功,这时,在异步操作成功之前注册的回调都会执行,但是在Promise异步操作成功这之后调用的then注册的回调就再也不会执行了,也就是永远只执行第一个fn

第四步:加入执行状态

Promises/A+规范中的2.1Promise States中明确规定了,pending可以转化为fulfilled或rejected并且只能转化一次,也就是说如果pending转化到fulfilled状态,那么就不能再转化到rejected。并且fulfilled和rejected状态只能由pending转化而来,两者之间不能互相转换。
image.png

  1. function Promise(fn) {
  2. var state = 'pending';
  3. var value = null;
  4. var callbacks = [];
  5. this.then = function (onFulfilled) {
  6. if (state === 'pending') {
  7. callbacks.push(onFulfilled);
  8. return this;
  9. }
  10. onFulfilled(value);
  11. return this;
  12. };
  13. function resolve(newValue) {
  14. value = newValue;
  15. state = 'fulfilled';
  16. setTimeout(function () {
  17. callbacks.forEach(function (callback) {
  18. callback(value);
  19. });
  20. }, 0);
  21. }
  22. fn(resolve);
  23. }
  24. let p = new Promise((resolve) => {
  25. resolve(1111);
  26. }).then((data) => {
  27. console.log(data);
  28. }).then((data) => {
  29. console.log(data);
  30. });

第五步:连通当前promise和后邻promise

  • then函数里面,传了一个回调函数,这个函数被当作参数

image.png

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

image.png

  1. let count = 0;
  2. function PromiseFn(fn) {
  3. count++;
  4. let recordCount = count;
  5. let state = 'pending';
  6. let value = null;
  7. // 执行队列
  8. let callbacks = [];
  9. this.then = function(onFulfilled) {
  10. return new PromiseFn((resolve, reject) => {
  11. // 桥梁,将新 Promise 的 resolve 方法,放到前一个 promise 的回调对象中
  12. handle({ onFulfilled, resolve });
  13. });
  14. };
  15. function handle(callback) {
  16. console.log(recordCount)
  17. // 判断如果状态为未完成,则加入到队列中
  18. if (state === 'pending') {
  19. callbacks.push(callback);
  20. return;
  21. }
  22. if (state === 'fulfilled') {
  23. // 如果then中没有回调函数,则结束
  24. if (!callback.onFulfilled) {
  25. callback.resolve(value);
  26. return;
  27. }
  28. // 处理回调
  29. const ret = callback.onFulfilled(value)
  30. // 处理下一个 promise 的resolve
  31. callback.resolve(ret)
  32. }
  33. }
  34. function resolve(newValue) {
  35. const fn = () => {
  36. console.log(state, recordCount, callbacks);
  37. if(state !== 'pending') return;
  38. state = 'fulfilled';
  39. value = newValue
  40. handelCb()
  41. }
  42. // 基于 PromiseA+ 规范
  43. setTimeout(fn, 0)
  44. }
  45. function handelCb() {
  46. while(callbacks.length) {
  47. const fulfiledFn = callbacks.shift();
  48. handle(fulfiledFn);
  49. };
  50. }
  51. fn(resolve)
  52. }
  53. // 如果没有添加then函数,则只是运行了一下函数
  54. // let p = new PromiseFn(this.test);
  55. let p2 = new PromiseFn(this.test).then((data) => {
  56. console.log(data)
  57. // return 'resolve again'
  58. }).then((data) => {
  59. console.log(data)
  60. });

我们常用的链式调用,是用在异步回调中,以解决”回调地狱”的问题,看如下代码,打印出来的东西跟promise不一样

  1. new Promise((resolve, reject) => {
  2. setTimeout(() => {
  3. resolve({ test: 1 })
  4. }, 1000)
  5. }).then((data) => {
  6. console.log('result1', data)
  7. //dosomething
  8. return test()
  9. }).then((data) => {
  10. console.log('result2', data)
  11. })
  12. function test(id) {
  13. return new Promise(((resolve) => {
  14. setTimeout(() => {
  15. resolve({ test: 2 })
  16. }, 5000)
  17. }))
  18. }
  19. //基于第一个 Promise 模型,执行后的输出
  20. //result1 { test: 1 }
  21. //result2 Promise {then: ƒ}

需要给resolve函数进行判断,自动执行promise函数

  1. function resolve(newValue){
  2. const fn = ()=>{
  3. if(state !== 'pending')return
  4. if(newValue && (typeof newValue === 'object' || typeof newValue === 'function')){
  5. const {then} = newValue
  6. if(typeof then === 'function'){
  7. // newValue 为新产生的 Promise,此时resolve为上个 promise 的resolve
  8. //相当于调用了新产生 Promise 的then方法,注入了上个 promise 的resolve 为其回调
  9. then.call(newValue,resolve)
  10. return
  11. }
  12. }
  13. state = 'fulfilled';
  14. value = newValue
  15. handelCb()
  16. }
  17. setTimeout(fn,0)
  18. }