Promise你把握不住?来看看异步转同步改造(下)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: Promise你把握不住?来看看异步转同步改造

先看koa怎么搞?

这个好办, 下面是一个简单的router(路由web API)。

我们看到在router.get 第二个参数加了async关键字修饰的方法。

根据ES6,我们知道async函数内可以使用await强制等待异步Promise函数的相应结果。

很明显,上面的runSql函数返回不是一个Promise对象的,所以这里先调用一个未实现的函数:prunSql。


router.get('/asynQuery', async function(ctx, next){
    //参考上面Promise使用,声明同步等待一个返回Promise对象的函数。
    var data = await prunSql('SELECT * FROM COMPANY;');
    ctx.body = JSON.stringify(data)
});

这是一个新的接口, 跟其他接口不一样的就是,它处理请求的方法是用async声明的异步函数。

我们需要改造runSql函数

const prunSql = function(sql){
    console.log('will run sql:', sql);
    return new Promise(function(resolve, reject){
        console.log('asyn run sql: ', sql);
        db.query(sql, function(error, result, fields){
            if(error){
                console.log('[%s] asyn error:', error);
                reject(error);
            }else{
                console.log('asyn result:', result);
                resolve(result);
            }
        });
    });
};

这就是改造好的prunSql,这里用了resolve函数把数据库查询结果传递出去。

这样在使用Promise的then可以获取到异步查询结果。

或者在一个异步响应的方法内await Promise对象,等待查询返回值。

看看使用Promise处理后的效果:

image.png

问题至此,迎刃而解!

具体用什么框架做接口不重要,理解整个思想才是重点。

贴一下代码, 下面的数据库查询库(db-lite.js),读者可自行更换成其他异步查询的库,进行改造,不必过多纠结一定要使用本文的runSql函数。

const koa = require('Koa');                                                 
const app = new koa()
var router = require('koa-router')();
var db = require('./db-lite');
router.get('/', function(ctx, next){ctx.body='Hello, geeklevin!'});
router.get('/query', function(ctx,next){
    db.runSql("SELECT * FROM COMPANY; ", function(result,fields){
        console.log('查询结果:', result);
        ctx.body = JSON.stringify(result);
        console.log('设置响应body成功!');
    });
    console.log('processing');
});
router.get('/asynQuery', async function(ctx, next){
    var data = await db.prunSql('SELECT * FROM COMPANY;');
    ctx.body = JSON.stringify(data)
});
app.use(router.routes());
const PORT = 8081
console.log('start app at port %s', PORT)
app.listen(PORT);

db-lite.js 代码:

const mysql =  require('mysql');
const db =  mysql.createConnection({
    host: "localhost",
    port: 3306,
    user: "root",
    password: "12345678"
});
const logDbStat = function(){
    console.log("db state %s and threadID %s", db.state, db.threadId);
    // console.log("db detail:", db);
}
logDbStat();
console.log('start to connect mysql');
db.connect(function(err){
    if(err){
        console.log('fail to connect db',err.stack);
        throw err;
    }
    logDbStat();
});
const close = function(){
    db.destroy();
    console.log('db disconnected');
    logDbStat();
};
var counter = 0;
const runSql = function(sql, callback){
    counter++;
    var cv = counter;
    console.log('run sql[%s] :[%s]',cv, sql);
    db.query(sql, function(error, result, fields){
        try{
            if(error) throw error;
        }finally{
            if(callback) callback(result, fields);
        }
    });
}
const prunSql = function(sql){
    console.log('will sql:', sql);
    return new Promise(function(resolve, reject){
        counter++;
        var cv = counter;
        console.log('asyn run sql[%s] :[%s]', cv, sql);
        db.query(sql, function(error, result, fields){
            if(error){
                console.log('[%s] asyn error:', cv, error);
                reject(error);
            }else{
                // console.log('[%s] asyn result:', cv, result);
                resolve(result);
            }
        });
    });
};
const myDb = 'demo20210330';
runSql("USE " + myDb);
module.exports.runSql = runSql;
module.exports.prunSql = prunSql;

总结

Promise结合async和await结合能够产生神奇的效果,也是很多新手过不去的坎,希望读者都能够熟练运用。

上面展示代码,读者可以自行思考,改造工作中使用的异步请求转化为同步调用。

篇幅有限,当然这本质上还是异步执行的,希望读者自行鞭策,思考理解。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
前端开发 JavaScript
如何处理 JavaScript 中的异步操作和 Promise?
如何处理 JavaScript 中的异步操作和 Promise?
26 1
|
2月前
|
JavaScript 前端开发
如何处理 Vue 中的异步操作和 Promise?
如何处理 Vue 中的异步操作和 Promise?
96 1
|
4天前
|
前端开发 JavaScript
Promise是JavaScript解决异步问题的构造器,代表未来的不确定值。
【6月更文挑战第27天】Promise是JavaScript解决异步问题的构造器,代表未来的不确定值。它避免了回调地狱,通过链式调用`.then()`和`.catch()`使异步流程清晰。
7 2
|
18天前
|
JSON 前端开发 JavaScript
ES6引入Promise和async/await解决异步问题
【6月更文挑战第12天】ES6引入Promise和async/await解决异步问题。Promise处理异步操作,有pending、fulfilled、rejected三种状态,支持链式调用和并行处理。async/await是基于Promise的语法糖,使异步代码更同步化,提高可读性。两者都是处理回调地狱的有效工具,开发者应根据需求选择合适的方式。
39 3
|
2月前
|
前端开发 JavaScript 安全
Promise/A+ 规范详解:打造健壮异步代码的必备知识(上)
Promise/A+ 规范详解:打造健壮异步代码的必备知识(上)
Promise/A+ 规范详解:打造健壮异步代码的必备知识(上)
|
2月前
|
前端开发 JavaScript
掌握 Promise.all:优雅处理多个异步操作
掌握 Promise.all:优雅处理多个异步操作
|
2月前
|
前端开发 JavaScript UED
使用Promise或者async/await处理游戏中的异步操作。
JavaScript中的Promise和async/await常用于处理游戏开发中的异步操作,如加载资源、网络请求和动画帧更新。Promise代表异步操作的结果,通过.then()和.catch()处理回调。async/await提供了一种更简洁的语法,使异步代码看起来更同步。在游戏循环中,使用async/await管理资源加载可提高代码可读性,但需注意避免阻塞UI线程,并妥善处理加载顺序、错误和资源管理,以保证游戏性能和稳定性。
23 2
|
2月前
|
前端开发 安全
Promise/A+ 规范详解:打造健壮异步代码的必备知识(下)
Promise/A+ 规范详解:打造健壮异步代码的必备知识(下)
Promise/A+ 规范详解:打造健壮异步代码的必备知识(下)
|
2月前
|
前端开发 JavaScript API
Promise.all() 的原理与实战:简化异步逻辑的不二选择
Promise.all() 的原理与实战:简化异步逻辑的不二选择
Promise.all() 的原理与实战:简化异步逻辑的不二选择
|
2月前
|
前端开发 JavaScript
JavaScript基础知识:什么是 Promise?如何使用它处理异步操作?
JavaScript基础知识:什么是 Promise?如何使用它处理异步操作?
34 1