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

简介: Promise你把握不住?来看看异步转同步改造

前言

先说一下上一篇NodeJS文章

NodeJS 后端开发 06 连接MySQL

,这一篇展示了一个数据库链接的db.js 工具库。


该工具库提供了一个runSql函数,它的运行方式是先提交SQL,然后再异步把查询结果回调传递给callback函数的。


这个函数只适用于提前加载数据的情况,比如预先缓存批量的查库结果。然后用户请求WebAPI的时候,直接读查询缓存。

这样会有下面的问题:


新数据入库了,本地缓存需要更新。

而且无法支持动态查询。

说这么多,直接用Koa做个接口演示一下查询效果吧。


代码展示,KOA做接口查询数据库

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');
});
//启动服务器
app.use(router.routes());
const PORT = 8081
console.log('start app at port %s', PORT)
app.listen(PORT);

先查看简单接口展示效果:

image.png

再看看/query接口

日志看到设置了响应体ctx.body成功了,可这时候请求已经结束了。

因为db.runSql函数不是同步执行了,/query这个接口执行这个函数,碰到函数结束了,当前请求处理完毕,没有设置请求体,所以响应Not Found。

image.png

看看Promise吧

var data = new Promise(function(resolve, reject){
    asynFunction(function(error, result){
          if(error){
               reject(error);
          }else{
               resolve(result);
          }
    });
});
async getData(){
    var result = await data();
    console.log('result is:', result);
}

就两段代码,第一段是构造Promise对象;第二段为调用Promise对象处理异步请求。


先说Promise。data是一个Promise对象,它内部调用了一个异步函数asynFunction(这个函数可以是查库,请求其他网站接口,消息队列获取数据等),但是它能够保证两个结果:


处理异步请求成功的时候调用resolve函数,传递result对象;

出错的时候调用reject函数,传递error对象。

就这么简单。


第二段代码就是一个声明了异步响应的函数,虽然内部调用的Promise对象,又套娃调用了异步函数,但是await语法糖,能够保证result变量赋值这一行同步执行,也就是getData会等待result赋值这一行异步调用执行完毕,再执行console.log。


这里稍微有点绕了,请读者停下来,好好思考整理一下。


简单来说就是,在async声明的异步函数中,同步等待Promise内部执行结果,就是,同步等待异步请求。


这样,异步转同步,很神奇吧!


像查询数据库这样的异步操作就能够在API中被等待,并响应给用户了,下面来代码了。


好,用koa接口得怎么做呢?需要在数据库调用端怎么调整呢?


下面是runSql的简化实现代码,我们要改造它


const runSql = function(sql, callback){
    console.log('will run sql:', sql);
    //这里是异步调用的,但是不是Promise实现,没有办法使用asyn,await来实现同步等待异步请求。
    db.query(sql, function(error, result, fields){
        try{
            if(error) throw error;
            console.log('query result:', result); 
        }finally{
            if(callback) callback(result, fields);
        }
    });
}

目录
相关文章
|
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