KrisGuoQin / Blog

博客,记录知识点与问题
0 stars 0 forks source link

Rxjs应用:先并发再串行 #4

Open KrisGuoQin opened 4 years ago

KrisGuoQin commented 4 years ago

需求背景

有一个表单,上面有上传图片和上传附件的功能,还有一些表单字段需要填写,最后提交表单。共有三个接口,上传图片接口,上传附件的接口,提交表单数据的接口。需要实现先上传图片和附件,获取到上传的地址后提交表单。

代码实现


import { from, zip } from 'rxjs';
import { concatMap } from 'rxjs/operators';

const makePromise = (name, delay) => new Promise((resolve, reject) => setTimeout(() => resolve(${name} done), delay));

const uploadImgs$ = from(makePromise('uploadImgs', 1000)); const uploadFiles$ = from(makePromise('uploadFiles', 2000)); const submitForm$ = from(makePromise('submitForm', 1000));

const subInst = zip( uploadImgs$, uploadFiles$ ).pipe( concatMap(val => { console.log('val', val); return submitForm$ }) ).subscribe( data => { console.log('data', data) }, error => { console.log('error', error) } );

// async await实现 async function submitForm () { const val = await Promise.all([ makePromise('uploadImgs', 1000), makePromise('uploadFiles', 2000) ]); console.log('val', val); const val2 = await makePromise('submitForm', 1000); console.log('val2', val2); } submitForm()


> ## 解读
实现的关键在于zip创建符。它的作用类似于我们衣服的拉链咬合的过程。会将我们输入的Observable组合起来,等待所有的的Observable每次完成之后输出结果,因为我们的只运行一次就结束了,所有只输出一次结果。它运行的时间取决于耗时最长的那个。待我们拿到结果后,可以结果传给另一个Observable,因为要继续处理Observable,所有我们需要用到高阶Observable。高阶Observable和高阶函数思想类似。输入Observable,返回Observable,我们的操作符会自动订阅返回的Observable,并将最终结果输出。

上面的代码假设uploadImgs$ 耗时1s,uploadFiles$耗时2s。所以zip处理的时间为2s,2s后将结果返回给下游。下游收到数据后,经过submitForm$处理,1s后返回结果。整个过程耗时3s多。

另外,zip除了可以作为静态方法外,还可以作为操作符;我们也可以mergeMap来处理高阶Observable。在这个实例中没有大的区别。

实际中,常用的都是ajax请求,这个实例为了演示使用了setTimeout。