疫情不出门,在家也无聊,打开浏览器翻看各个收藏夹,想找点好康的,突然发现了很久以前收藏的 30s一个代码片段,选择了JS语言,然后随机给我了一个代码片段www.30secondsofcode.org/js/s/pipe-a…,仔细一看,顿时惊到了,一行代码就写完了。。完全看不懂。。于是来了兴趣,便研究了起来。
这里展出这段代码:
const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); // EXAMPLES const sum = pipeAsyncFunctions( x => x + 1, x => new Promise(resolve => setTimeout(() => resolve(x + 2), 1000)), x => x + 3, async x => (await x) + 4 ); (async () => { console.log(await sum(5)); // 15 (after one second) })(); 复制代码
根据下面示例显示,1秒后会输出15,试着将5代入 sum函数
的几个箭头函数中累加了一下,结果没错,也就是说pipeAsyncFunctions
函数能将传进去的几个箭头函数依次执行一遍。再看到 reduce
函数,可以确定 p,f
两个参数想必就是 sum
传入的几个函数。
reduce
函数可以将数组中的每一项依次执行指定的回调函数:
arr.reduce(callback,[initValue]) // 回调函数有四个参数 callback(preValue,currentValue,?index,?arr) 复制代码
为了更好理解这段代码,我在 VS Code 中将这段代码改成了更适合理解的写法:
/* const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); */ const pipeAsyncFunctions = function(...fns) { console.log("fns:", fns); // fns: [ [Function], [Function], [Function], [Function] ] return function(arg) { console.log("arg:", arg); // arg: 5 return fns.reduce(function(p, f, index, arr) { return p.then(f); }, Promise.resolve(arg)); }; }; const sum = pipeAsyncFunctions( x => x + 1, x => x + 2, x => x + 3, x => x + 4 ); (async () => { console.log(await sum(5)); // 15 (after one second) })(); 复制代码
这里的 fns
即为传入的四个函数通过 三点运算符
形成的数组,通过打印输出可以证实这一点,同时确定了 arg,p,f
的值。之所以 fns
不是 sum(5)
传入的5,是因为 sum函数
实际接收的是 pipeAsyncFunctions
返回的函数,即 function(arg) {...}
。
const sum = pipeAsyncFunctions( x => x + 1, x => x + 2, x => x + 3, x => x + 4 ); // 等效于 const temp = pipeAsyncFunctions(...fns) //temp接受执行后的返回值 const sum = temp; /* const sum = function(arg) { return fns.reduce(function(p, f) { return p.then(f); }, Promise.resolve(arg)); }; */ 复制代码
对于 reduce
函数的 initValue
值要写成 Promise.resolve(arg)
,个人认为是为了将 arg
变成 Promise
对象,从而在回调函数中使 p
使用 then
方法执行 fns
中的各函数得到结果。所以要在最后使用 ES7的 async和await
语法等待异步函数执行完成再输出最终结果。
这段代码初一看显得有些难以理解,但是只需要将其进行拆分,转换成 ES5 的写法就会变得很容易理解了,最值得关注的便是 reduce
和 promise
的使用技巧了。当然,这样难以理解的高(zhuang)级(bi)技巧,平时研究一下原理就好,团队合作的时候就不要写了。好麻烦啊