首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用 bluebird 实现更强大的 Promise(3)处理集合

使用 bluebird 实现更强大的 Promise(3)处理集合

处理集合之前的代码示例都针对单个 Promise。在实际中,经常会需要与多个 Promise 进行交互。比如,读取单个文件的操作返回的是 Promise                对象,而我们需要等待若干个文件的读取操作都成功之后,再执行其他操作。Promise.all 可以接受一个 Iterable 参数,并返回一个新的                Promise。结果的 Promise 只有在 Iterable 中包含的全部 Promise 对象都满足时,才会满足;任何 Promise                出现错误会导致结果 Promise 被拒绝。新的 Promise 的最终结果是一个包含 Iterable 中 Promise 的结果的数组。该                Iterable 中可以包含任何值。如果值不是 Promise,则其值会直接出现在结果中,并不需要等待 Promise 完成。在代码清单8中,我们使用 Promise.all                来等待3个读取文件操作完成。
清单8.                Promise.all 使用示例
1
2
3
4
5
Promise.all([
  fs.readFileAsync(path.join(__dirname, '1.txt'), 'utf-8'),
  fs.readFileAsync(path.join(__dirname, '2.txt'), 'utf-8'),
  fs.readFileAsync(path.join(__dirname, '3.txt'), 'utf-8')
]).then(results => console.log(results.join(', '))).catch(console.error);




在很多情况下的做法都需要把 Iterable 中的对象转换成 Promise 之后,再等待这些 Promise 完成。对于这样的场景,可以使用                Promise.map。map 方法的第一个参数是 Iterable 对象,第二个参数是转换为 Promise                的方法,第三个参数是可选的配置对象,可以使用属性 concurrency 来控制同时运行的 Promise 的数量。在代码清单9代码清单9中,我们使用 Promise.map                把包含文件名称的数组转换成读取文件内容的 Promise 对象,再等待读取操作完成。的功能与代码清单8一样,但是实现更简单。
清单9.                Promise.map 的使用示例
1
2
3
Promise.map(['1.txt', '2.txt', '3.txt'],
   name => fs.readFileAsync(path.join(__dirname, name), 'utf-8')
).then(results => console.log(results.join(', '))).catch(console.error);




Promise.mapSeries 的作用与 Promise.map 相同,只不过 mapSeries 按照 Iterable                中的顺序依次遍历每个元素。
在有多个 Promise 时,如果只需要等待其中部分 Promise 完成,可以使用 Promise.some 并指定完成的 Promise                    数量。在代码清单10中,只需要等待2个文件读取操作完成即可。
清单10.                Promise.some 的使用示例
1
2
3
4
5
Promise.some([
fs.readFileAsync(path.join(__dirname, '1.txt'), 'utf-8'),
fs.readFileAsync(path.join(__dirname, '2.txt'), 'utf-8'),
fs.readFileAsync(path.join(__dirname, '3.txt'), 'utf-8')
], 2).then(results => console.log(results.join(', '))).catch(console.error);




Promise.any 相当于使用 Promise.some 并把数量设为1,不过 Promise.any                的结果不是一个长度为1的数组,还是具体的单个值。Promise.race 的作用类似 any,不过 race 的结果有可能是被拒绝的                Promise。因此推荐的做法是使用 any。
Promise.filter 可以等待多个 Promise 的完成,并对结果进行过滤。它实际上的效果相当于在 Promise.map 之后使用                Array 的 filter 方法来进行过滤。在代码清单11中,Promise.filter 用来过滤掉内容长度不大于1的文件。
清单11.                Promise.filter 的使用示例
1
2
3
4
5
Promise.filter([
fs.readFileAsync(path.join(__dirname, '1.txt'), 'utf-8'),
fs.readFileAsync(path.join(__dirname, '2.txt'), 'utf-8'),
fs.readFileAsync(path.join(__dirname, '3.txt'), 'utf-8')
], value => value.length > 1).then(results => console.log(results.join(', '))).catch(console.error);




Promise.each 对 Iterable 中的元素进行依次处理。处理方法也可以返回 Promise                对象来表示异步处理。只有对上一个元素的处理完成之后,才会处理下一个元素。
Promise.reduce 把多个 Promise 的结果缩减成单个值。其作用类似 Array 的 reduce 方法,但是可以处理 Promise                    对象。在代码清单12中,第一个参数是待处理的文件名称数组;第二个参数是进行累积操作的方法,total                表示当前累积值,用来与读取到的当前文件的长度相加;第三个参数是累积的初始值。从代码中可以看到,累积操作也可以返回 Promise                对象。Promise.reduce 会等待 Promise 完成。
清单12.                Promise.reduce 的使用示例
1
2
3
4
5
Promise.reduce(['1.txt', '2.txt', '3.txt'],
(total, name) => {
   return fs.readFileAsync(path.join(__dirname, name), 'utf-8').then(data => total + data.length);
}
, 0).then(result => console.log(`Total size: ${result}`)).catch(console.error);




Promise.all 用来处理动态数量的 Promise,Promise.join 用来处理固定数量的不相关的 Promise。
Promise.method 用来封装一个方法,使其返回 Promise。Promise.try 用来封装可能产生问题的方法调用,并根据调用结果来决定                Promise 的状态。
返回列表