实现Promise相关的allSettled,all和race方法
Promise.all (如果输入的任何 Promise 被拒绝,则返回的 Promise
将被拒绝,并带有第一个被拒绝的原因) Promise.race(这个返回的 promise
会随着第一个 promise 的敲定而敲定) allSettle(并带有描述每个 Promise
结果的对象数组。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 Promise .prototype .myAllsettled = function (arr ) { const ret = []; return new Promise ((resolve, reject ) => { for (let i = 0 ; i < arr.length ; i++) { arr[i].then (res => { ret[i] = res; if (res.length === arr.length ) { resolve (ret); } }).catch (err => { ret[i] = res; if (ret.length === arr.length ) { reject (res); } }) } }); }Promise .prototype .myRace = function (arr ) { return new Promise ((resolve, reject ) => { for (let i = 0 ; i < arr.length ; i++) { arr[i].then (res => { resolve (res); }).catch (err => { reject (err); }) } }); }Promise .prototype .myAll = function (arr ) { const ret = []; return new Promise ((resolve, reject ) => { for (let i = 0 ; i < arr.length ; i++) { arr[i].then (res => { ret[i] = res; if (ret.length === arr.length ) { resolve (ret); } }).catch (err => { reject (err); }) } }); }
实现all,apply和bind
考察this的指向 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 Function .prototype .myCall = function (obj ) { const fn = this ; const context = obj || window ; context.fn = fn; [].shift .call (arguments ); const ret = context.fn (...arguments ); delete context.fn ; return ret; }Function .prototype .myApply = function (obj ) { const fn = this ; const context = obj || window ; context.fn = fn; [].shift .call (arguments ); const arg2 = arguments [0 ]; const ret = context.fn (arg2); delete context.fn ; return ret; }Function .prototype .myBind = function (context ) { const fn = this ; [].shift .call (arguments ); const args = arguments ; context.fn = fn; const ret = function (...rest ) { const res = this === window ? context.fn (...arguments , rest) : fn (...arguments , rest); delete context.fn ; return res; } ret.prototype = fn.prototype ; return ret; }var value = 2 ;var foo = { value : 1 };function bar (name, age ) { this .habit = 'shopping' ; console .log (this .value ); console .log (name); console .log (age); } bar.prototype .friend = 'kevin' ;var bindFoo = bar.bind (foo, 'daisy' );var obj = new bindFoo ('18' );console .log (obj.habit );console .log (obj.friend );
实现new
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const myNew = function ( ) { if (typeof arguments [0 ] === 'function' ) { return ; } const obj = Object .create (null ); const Constructor : Function = arguments [0 ]; [].shift .call (arguments ); obj.__proto__ = Constructor .prototype ; const ret = Constructor .apply (obj, arguments ); return typeof ret === 'object' ? ret : obj; };
实现redux中的compose
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 function compose (middleware ) { return middleware.reduce ((total, next ) => (...args ) => total (next (...args))); }function compose (middleware ) { return function (cb ) { function dispatch (index ){ const fn = middleware[index]; const next = ( )=>dispatch (index+1 ); fn ? fn (next)() : cb () } return ()=> dispatch (0 ); } };const fn1 = (next ) => { return ()=> { console .log (1 ) next () console .log (2 ) } }const fn2 = (next ) => { return ()=> { console .log (3 ) next () console .log (4 ) } }const fn3 = (next ) => { return ()=> { console .log (5 ) next () console .log (6 ) } }const dispatch = compose ([fn1,fn2,fn3])(()=> console .log ("dispatch" ));dispatch ();
洋葱模型
考察闭包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 const middleware = []; middleware.push (function (next ) { console .log (1 ); next (); console .log (4 ); }); middleware.push (function (next ) { console .log (2 ); next (); console .log (5 ); }); middleware.push (function (next ) { console .log (3 ); next (); console .log (6 ); });function compose (middleware ) { let i = 0 ; const next = ( ) => { const fn = middleware[i++]; if (!fn) { return ; } fn (next); } return function ( ) { next (); } }
curry
考察闭包和递归 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 function add (x, y, z ) { return x + y + z }const currying = function (fn ) { let ret = 0 ; let i = 0 ; const len = fn.length ; const _fn = function ( ) { ret += [].reduce .call (arguments , (pre, cur ) => { i++; return pre + cur; }, 0 ); if (i === len) { return ret; } return _fn; } return _fn }var curryAdd = currying (add)console .log (curryAdd (1 , 2 )(3 )) console .log (curryAdd (1 , 2 )()(3 )) console .log (curryAdd (1 )(2 )(3 )) console .log (curryAdd (1 , 2 , 3 ))
## 并发任务数控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class Scheduler { taskQueue = []; runingCount = 0 ; add (task ) { return new Promise ((success, failed ) => { this .taskQueue .push ({ task, success, failed }); this .excuteTask () }) } excuteTask ( ) { if (this .taskQueue .length > 0 && this .runingCount < 2 ) { const { task, success, failed } = this .taskQueue .shift (); this .runingCount ++; task ().then (success, failed).finally (()=> { this .runingCount -- this .excuteTask () }); } } } const timeout = (time ) => new Promise (resolve => { setTimeout (resolve, time) })const scheduler = new Scheduler ()const addTask = (time, order ) => { scheduler.add (() => timeout (time)) .then (() => { console .log (order) }) }addTask (2000 , '1' )addTask (6000 , '2' )addTask (3000 , '3' )addTask (8000 , '4' )
## Promise串行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 const timeout = ms => new Promise ((resolve, reject ) => { setTimeout (() => { resolve (); }, ms); });const ajax1 = ( ) => timeout (2000 ).then (() => { console .log ('1' ); return 1 ; });const ajax2 = ( ) => timeout (1000 ).then (() => { console .log ('2' ); return 2 ; });const ajax3 = ( ) => timeout (2000 ).then (() => { console .log ('3' ); return 3 ; });function mergePromise (arr ) { const ret = []; return new Promise ((resolve, reject ) => { arr.reduce ((pre, cur ) => { return pre.then (cur).then (res => { ret.push (res); if (ret.length === arr.length ) { resolve (ret) } }); }, Promise .resolve ()); }) }mergePromise ([ajax1, ajax2, ajax3]).then (data => { console .log ('done' ); console .log (data); });
打印顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 async function async1 ( ) { console .log ('async1 start' ); await async2 (); console .log ('async1 end' ); }async function async2 ( ) { await async3 (); console .log ('async2' ); }async function async3 ( ) { console .log ('async3' ); }console .log ('script start' );setTimeout (function ( ) { console .log ('setTimeout' ); }, 0 )async1 ();new Promise (function (resolve ) { console .log ('promise1' ); resolve (); }).then (function ( ) { console .log ('promise2' ); });console .log ('script end' ); script start async1 start async3 promise1 script end async2 promise2 async1 endundefined setTimeout async function async1 ( ) { console .log ('async1 start' ); await async2 (); console .log ('async1 end' ); }async function async2 ( ) { console .log ('async2' ); }console .log ('script start' );setTimeout (function ( ) { console .log ('setTimeout' ); }, 0 )async1 ();new Promise (function (resolve ) { console .log ('promise1' ); resolve (); }).then (function ( ) { console .log ('promise2' ); });console .log ('script end' ); script start async1 start async2 promise1 script end async1 end promise2undefined setTimeout const first = ( ) => (new Promise ((resolve, reject ) => { console .log (3 ); let p = new Promise ((resolve, reject ) => { console .log (7 ); setTimeout (() => { console .log (5 ); resolve (6 ); }, 0 ) resolve (1 ); }); resolve (2 ); p.then ((arg ) => { console .log (arg); }); }));first ().then ((arg ) => { console .log (arg); });console .log (4 );3 7 4 1 2 5
this的指向
变量提升
参考文章
https://juejin.cn/post/7199321655734190140#heading-13