• 介绍两个JavaScript 语法提案:数组分组和Promise.withResolvers
  • 发布于 2个月前
  • 194 热度
    0 评论
今天带大家了解两个刚刚进入 stage3 阶段的新的 JavaScript 语法提案。

数组分组
在日常编程中,我们常常需要对数组的元素进行分类和分组,数组分组是一种极其常见的操作,SQL 的 GROUP BY 语句和 MapReduce 编程就是最好的例子。例如,现在有一组数字,我们可能需要将它们按照奇偶进行分组。为了更方便地完成这类操作,这份提案提出了一种新的方法来简化数组中的分组操作。

在这个提案中,提供了两个新的方法:Object.groupBy 和 Map.groupBy。前者返回一个无原型的对象,这可以使解构更为方便,并且可以防止与全局 Object 属性冲突。
const array = [1, 2, 3, 4, 5];
// 堆代码 duidaima.com
// Object.groupBy根据任意键对项进行分组。
// 在这个例子中,我们根据键的奇偶性进行分组
Object.groupBy(array, (num, index) => {
return num % 2 === 0 ? 'even': 'odd';
});
// => { odd: [1, 3, 5], even: [2, 4] }
后者返回一个常规的 Map 实例,它允许对复杂键类型进行分组。
// Map.groupBy在Map中返回项,适用于使用对象键进行分组。
const odd = { odd: true };
const even = { even: true };
Map.groupBy(array, (num, index) => {
return num % 2 === 0 ? even: odd;
});
// => Map { {odd: true}: [1, 3, 5], {even: true}: [2, 4] }
这个提案其实也就是借鉴的已经被广泛使用的 Lodash 库的 _.groupBy 方法。

Promise.withResolvers
当手动执行 Promise 时,我们必须要传递一个执行回调,它接受两个参数:一个 resolve 函数,它负责触发 Promise 的 resolve 状态,以及一个 reject 函数,它触发 reject 状态。如果回调可以嵌入对异步函数的调用,这个调用最终就会触发 resolve 或 reject,例如事件侦听器的注册,这种场景的使用还可以接受。
const promise = new Promise((resolve, reject) => {
  asyncRequest(config, response => {
    const buffer = [];
    response.on('data', data => buffer.push(data));
    response.on('end', () => resolve(buffer));
    response.on('error', reason => reject(reason));
  });
});
但有的时候我们可能会希望在实例化 Promise 后再去配置它的 resolve 和 reject 行为。这就需要一个繁琐的解决方法来从回调范围中提取 resolve 和 reject 函数:
let resolve, reject;
const promise = new Promise((res, rej) => {
  resolve = res;
  reject = rej;
});
asyncRequest(config, response => {
  const buffer = [];
  response.on('callback-request', id => {
    promise.then(data => callback(id, data));
  });
  response.on('data', data => buffer.push(data));
  response.on('end', () => resolve(buffer));
  response.on('error', reason => reject(reason));
});
我们可能还需要将resolve/reject 传递给多个调用者,那就必须得用这种方式实现:
let resolve = () => { };
let reject = () => { };

function request(type, message) {
  if (socket) {
    const promise = new Promise((res, rej) => {
      resolve = res;
      reject = rej;
    });
    socket.emit(type, message);
    return promise;
  }

  return Promise.reject(new Error('Socket unavailable'));
}

socket.on('response', response => {
  if (response.status === 200) {
    resolve(response);
  }
  else {
    reject(new Error(response));
  }
});

socket.on('error', err => {
  reject(err);
});
这就是我们可能会经常重写的样板代码,这个提案给 Promise 方法新增了一个静态方法 withResolvers,它可以非常简单的直接让我们获取 resolve/reject :
// 堆代码 duidaima.com
const { promise, resolve, reject } = Promise.withResolvers();
最后
你怎么看?欢迎在评论区留言
用户评论