关于一段ES6代码的探讨

说在前面的话

疫情不出门,在家也无聊,打开浏览器翻看各个收藏夹,想找点好康的,突然发现了很久以前收藏的 30s一个代码片段,选择了JS语言,然后随机给我了一个代码片段https://www.30secondsofcode.org/js/s/pipe-async-functions/,仔细一看,顿时惊到了,一行代码就写完了。。完全看不懂。。于是来了兴趣,便研究了起来。

这里展出这段代码:

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 的写法就会变得很容易理解了,最值得关注的便是 reducepromise 的使用技巧了。当然,这样难以理解的高(zhuang)级(bi)技巧,平时研究一下原理就好,团队合作的时候就不要写了。好麻烦啊

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值