今天带大家了解两个刚刚进入 stage3
阶段的新的 JavaScript
语法提案。
数组分组
在日常编程中,我们常常需要对数组的元素进行分类和分组,数组分组是一种极其常见的操作,SQL
的 GROUP BY
语句和 MapReduce
编程就是最好的例子。例如,现在有一组数字,我们可能需要将它们按照奇偶进行分组。为了更方便地完成这类操作,这份提案提出了一种新的方法来简化数组中的分组操作。
在这个提案中,提供了两个新的方法:Object.groupBy
和 Map.groupBy
。前者返回一个无原型的对象,这可以使解构更为方便,并且可以防止与全局 Object
属性冲突。
const array = [1, 2, 3, 4, 5];
// 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
:
const { promise, resolve, reject } = Promise.withResolvers();
最后
你怎么看?欢迎在评论区留言
参考:
- https://github.com/tc39/proposal-promise-with-resolvers
- https://github.com/tc39/proposal-array-grouping