promise使用初探


title: promise使用初探
date: 2018-12-29 16:10:48
categories: 小游戏
tags: js

promise简介


Promise是异步编程的一种解决方案,比传统的解决方案 — 回调函数和事件——更合理和更强大。

为什么要用他

我们考虑这么一个场景,我们需要登陆拿到用户的token,然后再利用用户的token取取用户的信息,最后利用用户的相关信息去拿他的好友的相关信息。假设我们提供如下的模拟接口:

class Api{

    getToken(callBack) {
        setTimeout(() =>{
            callBack && callBack("123");
        }, 200);    
    }

    getUserInfo(token, callBack) {
        setTimeout(() => {
            callBack && callBack(token + "4");
        }, 200)
    }

    getOtherInfo(id, callBack) {
        setTimeout(() => {
            callBack && callBack(id + "5");
        }, 200)
    }
}

那么直接用回调来实现的话,我们的调用如下:

var api = new Api();

api.getToken((token) => {
    // 获得了token
    api.getUserInfo(token, (userInfo) => {
        // 获得了userInfo
        api.getOtherInfo(userInfo, (getOtherInfo) => {
            console.log(" get other info " + getOtherInfo);
        })
    })
})

一个很常见的场景,但是我们直接用callBack来实现的话,就会这么多嵌套的回调,这只是一个很简单的例子,试想一下,如果需求更复杂一点的话,回调就会更加复杂,如果要考虑代码的健壮性的话,加上异常处理,那简直就不能忍受了。
在这个时候,promise就站出来了,我们可以通过使用他,大大简化代码的嵌套,避免回调地狱。

promise简单用法

我们稍微调整一下前面的api,我们使用Promise的方式来实现,调整如下:

class Api2{

    getToken() {
        return new Promise((reslove, reject) => {
            setTimeout(() =>{
                reslove && reslove("123");
            }, 200); 
        }) 
    }

    getUserInfo(token) {
        return new Promise((reslove, reject) => {
            setTimeout(() => {
                reslove && reslove(token + "4");
            }, 200)
        })
    }

    getOtherInfo(id) {
        return new Promise((reslove, reject) => {
            setTimeout(() => {
                reslove && reslove(id + "5");
            }, 200)
        })
    }
}

在使用了```Promise``之后,那么我们的调用怎么去调用呢?很简单,如代码所示:

var api = new Api2();

api.getToken().then(function(reslove, reject) {
    console.log("token = "+ reslove);
    api.getUserInfo(reslove).then((reslove, reject) => {
        console.log("info = "+ reslove);
        api.getOtherInfo(reslove).then((reslove, reject) => {
            console.log("friend Id = "+ reslove);
        });
    });
})

可以看到,在使用了Promise之后,代码明显简化了很多。

不知道是怎么看简化的,明显更复杂好吧。
不要着急,我们可以可以一步一步来进行简化。下面开始我们的简化之旅。

promise的链式用法

Promise有一个很棒的特性:Promise.prototype.then()Promise.prototype.catch()返回Promise对象,这就使得我们可以将这些promise连接成一个promise链。通过这种方法,我们可以将这些回调函数放在一个缩进层次里。与此同时,我们使用了箭头函数简化了回调函数声明。
对比之前的回调地狱,使用promise链使得代码的可读性大大提高并且拥有着更好的序列感。

var api = new Api2();

api.getToken().then((reslove, reject) => {
    console.log("token = "+ reslove);
     return api.getUserInfo(reslove);
}).then((userInfo) => {
    return api.getOtherInfo(userInfo);
}).then((friendInfo) => {
    console.log("friend id = " + friendInfo);
});

是不是明显就没有那么多回调了,看着是不是舒服多了。哈哈,不过这还没完,这代码看起来还是稍微有点复杂,虽然没有一层一层的回调了,但是链起来好像也有点长,让我们继续来优化他。

使用Async/Await将异步“变”同步

我们首先来看调用的函数代码:

async function getFriend() {
    const api = new Api2();
    const token = await api.getToken();
    const userInfo = await api.getUserInfo(token);
    const friend = await api.getOtherInfo(userInfo);
    console.log("friend " + friend);
}


是不是顿时感觉就清爽很多了。
我们可以通过await将回调“变”成同步方法来使用,我们只有执行完了api.getToken之后,才能继续执行下面的方法。前提是必须要在异步方法里,即被async修饰的方法里面。从上面的方法来说,我们可以将它当作一个同步方法来使用了。

异常处理

我们先来看,如果使用回调的话,如果要进行异常处理该怎么写吧。

var api = new Api();

try{
    api.getToken((token) => {
        // 获得了token
        try{
            api.getUserInfo(token, (userInfo) => {
                // 获得了userInfo
                try{
                    api.getOtherInfo(userInfo, (getOtherInfo) => {
                        console.log(" get other info error" + getOtherInfo);
                    })
                } catch(e) {
                    console.log("getOtherInfo " + e);
                }
            })
        } catch(e) {
            console.log("getUserInfo error" + e);
        }
    })    
} catch(e) {
    console.log("getToken error" + e);
}

这么多try-catch,是不是双爽歪歪,如果我们还要加入流程控制、异常处理,这简直就是异常灾难。那么我们接下来看怎么用Promise进行异常处理。

先上代码:

api.getToken().then((reslove, reject) => {
    console.log("token = "+ reslove);
     return api.getUserInfo(reslove);
}).then((userInfo) => {
    return api.getOtherInfo(userInfo);
}).then((friendInfo) => {
    console.log("friend id = " + friendInfo);
}).catch((err) =>  {
    console.log("error " + err);
});

链式的调用,我们只需要在在后面加上一条异常处理的catch()即可,和前面的若干个try-catch相比是不是简单很多。当然,我们也可以用awit-async组合+try-catch来处理异常。示例代码如下:

async function getFriend() {
    try{
        const api = new Api2();
        const token = await api.getToken();
        const userInfo = await api.getUserInfo(token);
        const friend = await api.getOtherInfo(userInfo);
        console.log("friend " + friend);
    } catch(e) {
        console.error("error: "+ e);
    } 
}

总结

通过使用Promise,可以大大简化我们回调的嵌套,可以使得我们的代码更加简洁、易读。

参考资料

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值