js异步编程高级使用(常用)

1.引言

    随着自己对node后端的了解加深,发现自己对于JavaScript的高级用法需要更加深入的理解,否则永远都是码砖,难有提升。于是总结了如下一个在javascript编程里面比较常用的例子作以理解并分享,如果不对,欢迎批评指正。

2.问题溯源

    使用koa框架,某接口需要查询数据库数据,查询完数据之后需要进一步处理,最后使用koa的ctx.body返回请求数据。

3.问题解决

    直接放代码如下(当时因为项目紧急,核心部分借鉴的大佬的代码):

//第一段代码:使用单例模式进行数据库的长连接
//归属文件:/config/connect-mysql.js
const mysql = require("mysql");
module.exports=class MysqlConnect {//利用单例模式处理数据库的连接
    constructor() {
        if (!MysqlConnect.instance) {
            MysqlConnect.instance = mysql.createConnection({
                connectionLimit: 20,
                host: 'localhost',
                port: 3306,
                user: 'zhangsan',
                password: 'admin123',
                database: 'easyclothing'
            });
            MysqlConnect.instance.connect((err) => {
                console.log("MySQL数据库连接成功!")
            });
        }
        return MysqlConnect.instance;
    }
}
//第二段代码:查询数据库,数据查询完成后调用回调函数
//归属文件:/models/tool.js
const MysqlConnect = require("../config/connect-mysql");
const mysqlDB = new MysqlConnect();
module.exports=function getToolList(callback) {
    const promise = new Promise((resolve, reject) => {
        const sql = "select * from tool";
        mysqlDB.query(sql, (err, result) => {
            if (err) {
                console.log("tool数据表查询失败,原因:", err);
                reject(err);
            }
            resolve(result);
        })
    });
    promise.then((res) => {
        callback(res);
    });
    promise.catch((err) => {
        console.log("函数调用失败!", err);
    })
}
//第三段代码:接受回调数据并响应用户请求
//归属文件:/router/tool.js(与代码无关)
const getToolList = require("../models/tool");
module.exports = async (ctx) => {
    //代码的执行顺序说明:Promise正常执行,然后是then,最后是setTimeout
    
    //async:用于声明函数是一个异步函数,确保返回一个Promise对象,
    //下面的使用主要是提高代码的优雅度(本身就有Promise 返回)
    async function delay(time) {
        return new Promise((resolve, reject) => {
            function callback(res) {
                resolve(res);
            }
            setTimeout(() => {
                getToolList(callback);
            }, time);
        });
    }
    //await:用于等待该异步函数执行完成
    await delay(0).then((toolList) => {
        ctx.body = {
            data: toolList
        }
    });
};

4.给出自己的理解

    虽然自己也曾写过async、await以及浏览器事件循环机制相关的文章总结,但是事实证明使用起来还是有些生硬,解释第三段代码:
(1)async关键字,更像是为了方便快速使用await获取一个Promise 的成功返回的数据;保证函数最终返回的是一个Promise 数据,如果不是Promise数据,那么封装成一个Promise 数据,如果返回的已经是Promise,那么不变;
(2)在上述代码中,使用await是为了与最外层的async配套,而不是async delay函数,async 的作用可以理解成提高代码的“优雅度”或者说是可阅读性。代码首先执行delay函数,然后将time=0参数传入,获取到一个Promise对象,具体内容如下:

new Promise((resolve, reject) => {
        function callback(res) {
            resolve(res);
        }
        setTimeout(() => {
            getToolList(callback);
        }, 0);
    });

然后代码的.then函数会等待处于pending状态的Promise进入resolve态,直到resolve执行也就是数据处理完毕才调用接下来的部分,最后也就成功返回想要的数据。
(3)问题来了,好端端的为什么要是用setTimeout这个不常用的工具呢,其实,还是为了使内部依然是异步调用,处于这个假设,代码修改如下依然可以正常运行,得证!:

async function delay(time) {
        return new Promise((resolve, reject) => {
            function callback(res) {
                resolve(res);
            }
            // setTimeout(() => {
            //     getToolList(callback);
            // }, time);
            (async function test() {
                getToolList(callback);
            }());
        });
    }

(4)进一步分析,这里的async其实可以不要,因为代码顺序执行,所以可以再简化:

async function delay(time) {
        return new Promise((resolve, reject) => {
            function callback(res) {
                resolve(res);
            }
            // setTimeout(() => {
            //     getToolList(callback);
            // }, time);
            getToolList(callback);
        });
    }

最终得出:大佬给的代码的setTimeout其实可以省略,如果不明白代码的执行流程那么,说真的,很可能会由于改动后代码运行错误,到处瞎归因,哈哈哈!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jerry说前后端

请作者喝杯冰阔落~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值