函数式的异步处理

   假设我们有一系列需要调用的网络请求,有的并行,有点串行,有的需要处理异常,那么如何打造这样一条执行链呢?

先模拟一些网络请求。

let R= require('ramda');

const getUser = (userId) =>  new Promise((resolve,reject) => {
    setTimeout(() => {
        resolve({users: {
            JOE: {
              name: 'Joe',
              followers: ['STEVE', 'SUZY']
            }
          }})
    }, 500);
});
const getNameList = () => new Promise((resolve,reject)=>{
    setTimeout(() => {
        resolve([
            {name:'name1'},
            {name:'name2'},
            {name:'name3'}
        ])
    }, 400);
});

const getProductByUserName = (name) => new Promise((resolve,reject)=>{
    setTimeout(() => {
        // reject(new Error('nothing'))
        resolve('success');
    }, 1000);
})

我们假设第一个串行,后两个并行(并且捕获错误)

1.命令式写法:

const getResult = async (userId)=> {
    let {users:{JOE:{name}}} = await getUser('userId');
    //捕获错误
    let tasks = [getProductByUserName(name),getNameList()].map(v=>v.catch(err=>err));
    //并发执行
    return Promise.all(tasks);
    //不用PromiseAll的写法:
    //return [await p1,await p2,await p3];
}
const result = getResult().then((v)=>console.log(v));

2.函数式写法:

1.使用composeP,composeP是针对promise对象的组合子(自动将下一个调用放在then里面)

//并发执行
const parallel = R.compose(
    (v)=>Promise.all(v),//这样转一下是因为直接传入Promise.all,node下会报错,原因不明
    (v)=>[getNameList(),getProductByUserName(v).catch(err=>err)],
    R.path(['users','JOE','name'])
)
const getResult = R.composeP(
    parallel,
    getUser
);

const result = getResult().then((v)=>console.log(v));

但是这样写也并不怎么清晰,我们尝试创建一个通用的并发执行的方法。

//并行执行promise,该方法接受两个参数,第一个是promise方法数组,第二个是以上方法需要的参数,方法和参数是一一对应的,不需要参数的方法,需放在数组末尾。
//并行promise
const parallel = (...Ps) =>  R.compose(
                                (v)=>Promise.all(v),
                                R.map(R.otherwise(R.identity)),
                                (...params)=>R.reduce((arr,fn)=>[...arr,fn(params.shift())],[],Ps)
                            )

重新组织我们的调用:

const getResult = R.composeP(
    parallel(getProductByUserName,getNameList),
    R.path(['users','JOE','name']),
    getUser
);

const time = new Date();
getResult('userId').then((result)=>{
    console.log("time:",new Date() - time);
    console.log("TCL: result", result)
}).catch(err=>console.log(err)) 

这样的实现可以用清晰的代码处理复杂的异步调用(即使再复杂,也只是增加了composeP组合的长度而已)

(以上代码都经过测试,直接可用。)之后想讲一下函数提升。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值