返回顶部
首页 > 资讯 > 前端开发 > node.js >浅谈Express异步进化史
  • 330
分享到

浅谈Express异步进化史

进化史浅谈Express 2022-06-04 17:06:43 330人浏览 安东尼
摘要

1、导言 在 javascript 的世界里,异步(由于JavaScript的单线程运行,所以JavaScript中的异步是可以阻塞的)无处不在。 Express 是 node 环境中非常流行的WEB服务端

1、导言

javascript 的世界里,异步(由于JavaScript的单线程运行,所以JavaScript中的异步是可以阻塞的)无处不在。

Express 是 node 环境中非常流行的WEB服务端框架,有很大比例的 Node Web应用 采用了 Express。

当使用 JavaScript 编写服务端代码时,我们无可避免的会大量使用到异步。随着 JavaScript、Node 的进化,我们的异步处理方式,也就随之进化。

接下来,我们就来看看 Express 中异步处理的进化过程。

2、JavaScript的异步处理

在异步的世界里,我们需要想办法获取的异步方法完毕的通知,那在 JavaScript 中,会有哪些方式呢?

2.1、回调

回调是 js 中最原始,也是最古老的异步通知机制。


function asyncFn(callback) {
 // 利用setTimeout模拟异步
 setTimeout(function () {
  console.log('执行完毕');
  callback(); // 发通知
 }, 2000);
}

asyncFn(function () {
 console.log('我会在2s后输出');
});

2.2、事件监听

要获取结果的函数,监听某个时间。在异步方法完成后,触发该事件,达到通知的效果。

2.3、发布/订阅

通过观察者模式,在异步完成时,修改发布者。这个时候,发布者会把变更通知到订阅者。

2.4、Promise

Promise 是回调函数的改进。使用它, 我们可以将异步平行化,避免回调地狱。


function asyncFn() {
 return new Promise((resolve, reject) => {
  // 利用setTimeout模拟异步
  setTimeout(function () {
   console.log('执行完毕');
   resolve(); // 发通知(是否有感觉到回调的影子?)
  }, 2000);
 });
}

asyncFn()
 .then(function () {
  console.log('我会在2s后输出');
 });

2.5、生成器(Generator)

Generator 函数是 es6 提供的一种异步编程解决方案。

以下代码只是简单演示,实际上 Generator 的使用过程,相对是比较复杂的,这是另外一个话题,本文暂且不表。


function asyncFn() {
 return new Promise((resolve, reject) => {
  // 利用setTimeout模拟异步
  setTimeout(function () {
   console.log('执行完毕');
   resolve(); // 发通知(是否有感觉到回调的影子?)
  }, 2000);
 });
}

function* generatorSync() {
 var result = yield asyncFn();
}

var g = generatorSync();
g.next().value.then(()=>{
 console.log('我会在2s后输出');
});

2.6、async...await

可以说是当前 JavaScript 中,处理异步的最佳方案。


function asyncFn() {
 return new Promise((resolve, reject) => {
  // 利用setTimeout模拟异步
  setTimeout(function () {
   console.log('执行完毕');
   resolve(); // 发通知(是否有感觉到回调的影子?)
  }, 2000);
 });
}

async function run(){
 await asyncFn();
 console.log('我会在2s后输出');
}

run();

3、Express中的异步处理

在Express中,我们一般常用的是方案是:回调函数、Promise、以及async...await。

为了搭建演示环境,通过 express-generator 初始化一个express项目。一般的服务端项目,都是路由调用业务逻辑。所以,我们也遵循这个原则:

打开 routs/index.js,我们会看到如下内容,以下Demo就以此文件来做演示。


var express = require('express');
var router = express.Router();


router.get('/', function(req, res, next) {
 res.render('index', { title: 'Express' });
});

module.exports = router;

3.1、回调函数处理Express异步逻辑

在 Express 中,路由可以加载多个中间件,所以我们可以把业务逻辑按照中间件的写法进行编写。这样通过一层层的next,就能非常方便的拆分异步逻辑。


var express = require('express');
var router = express.Router();

function asyncFn(req, res, next) {
 setTimeout(() => {
  req.user = {}; // 设置当前请求的用户
  next();
 }, 2000);
}

function asyncFn2(req, res, next) {
 setTimeout(() => {
  req.auth = {}; // 设置用户权限
  next();
 }, 2000);
}

function asyncFn3(req, res, next) {
 setTimeout(() => {
  res.locals = { title: 'Express Async Test' }; // 设置数据
  res.render('index'); // 响应
 }, 2000);
}


router.get('/', asyncFn, asyncFn2, asyncFn3); // 一步步执行中间件

module.exports = router;

3.2、Promise 处理Express异步逻辑

该方案中,将多个业务逻辑,包装为返回 Promise 的函数。通过业务方法进行组合调用,以达到一进一出的效果。


var express = require('express');
var router = express.Router();

function asyncFn(req, res) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   req.user = {}; // 设置当前请求的用户
   resolve(req);
  }, 2000);
 });
}

function asyncFn2(req) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   req.auth = {}; // 设置用户权限
   resolve();
  }, 2000);
 });
}

function asyncFn3(res) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   res.locals = { title: 'Express Async Test' }; // 设置数据
   res.render('index'); // 响应
  }, 2000);
 });
}

function doBizAsync(req, res, next) {
 asyncFn(req)
  .then(() => asyncFn2(req))
  .then(() => asyncFn3(res))
  .catch(next); // 统一异常处理
};


router.get('/', doBizAsync);

module.exports = router;

3.3、async...await 处理Express异步逻辑

实际上,该方案也是需要 Promise 的支持,只是写法上,更直观,错误处理也更直接。

需要注意的是,Express是早期的方案,没有对async...await进行全局错误处理,所以可以采用包装方式,进行处理。


var express = require('express');
var router = express.Router();

function asyncFn(req) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   req.user = {}; // 设置当前请求的用户
   resolve(req);
  }, 2000);
 });
}

function asyncFn2(req) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   req.auth = {}; // 设置用户权限
   resolve();
  }, 2000);
 });
}

function asyncFn3(res) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {

  }, 2000);
 });
}

async function doBizAsync(req, res, next) {
 var result = await asyncFn(req);
 var result2 = await asyncFn2(req);
 res.locals = { title: 'Express Async Test' }; // 设置数据
 res.render('index'); // 响应
};

const tools = {
 asyncWrap(fn) {
  return (req, res, next) => {
   fn(req, res, next).catch(next); // async...await在Express中的错误处理
  }
 }
};


router.get('/', tools.asyncWrap(doBizAsync)); // 需要用工具方法包裹一下

module.exports = router;

4、总结

虽然 koa 对更新、更好的用法(koa是generator,koa2原生async)支持的更好。但作为从 node 0.x 开始跟的我,对 Express 还是有特殊的好感。

以上的一些方案,已经与 koa 中使用无异,配合 Express 庞大的生态圈,无异于如虎添翼。

本文GitHub地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: 浅谈Express异步进化史

本文链接: https://lsjlt.com/news/12417.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 浅谈Express异步进化史
    1、导言 在 Javascript 的世界里,异步(由于JavaScript的单线程运行,所以JavaScript中的异步是可以阻塞的)无处不在。 Express 是 node 环境中非常流行的Web服务端...
    99+
    2022-06-04
    进化史 浅谈 Express
  • 浅谈Redis的异步机制
    目录前言一、Redis 的阻塞点4 类交互对象和具体的操作之间的关系:切片集群实例交互时的阻塞点二、可以异步执行的阻塞点三、异步的子线程机制总结前言 命令操作、系统配置、关键机制、硬...
    99+
    2024-04-02
  • 浅谈Node.js之异步流控制
    前言 在没有深度使用函数回调的经验的时候,去看这些内容还是有一点吃力的。由于Node.js独特的异步特性,才出现了“回调地狱”的问题,这篇文章中,我比较详细的记录了如何解决异步流问题。 文章会很长,而且这篇...
    99+
    2022-06-04
    浅谈 Node js
  • 浅谈node.js中async异步编程
    1.什么是异步编程? 异步编程是指由于异步I/O等因素,无法同步获得执行结果时, 在回调函数中进行下一步操作的代码编写风格,常见的如setTimeout函数、ajax请求等等。 示例: for (v...
    99+
    2022-06-04
    浅谈 node async
  • 浅谈Node异步编程的机制
    本文介绍了Node异步编程,分享给大家,具体如下: 目前的异步编程主要解决方案有: 事件发布/订阅模式 Promise/Deferred模式 流程控制库 事件发布/订阅模式 Node自身提供...
    99+
    2022-06-04
    浅谈 机制 Node
  • 浅谈servlet3异步原理与实践
    一、什么是Servletservlet 是基于 Java 的 Web 组件,由容器进行管理,来生成动态内容。像其他基于 Java 的组件技术一样,servlet 也是基于平台无关的 Java 类格式,被编译为平台无关的字节码,可以被基于 J...
    99+
    2023-05-31
    servlet 异步
  • 浅谈 PHP 函数的异步编程
    在 php 中,异步编程允许在不阻塞执行流的情况下执行耗时任务。实现异步编程的技术包括:回调函数:函数指针,在另一个函数执行完成后执行代码。协程:轻量级多任务机制,允许在同一线程中切换多...
    99+
    2024-05-05
    php 异步编程
  • 浅谈MySQL8.0 异步复制的三种方式
    本实验中分别针对空库、脱机、联机三种方式,配置一主两从的mysql标准异步复制。只做整服务器级别的复制,不考虑对个别库表或使用过滤复制的情况。 实验环境 [root@slave2 ~]# cat /etc/ho...
    99+
    2022-05-26
    MySQL8.0 异步复制 MySQL 异步复制
  • 如何进行Java 同步机制浅谈
    如何进行Java 同步机制浅谈,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Java对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了synchronized关键字就...
    99+
    2023-06-03
  • 浅谈Spring @Async异步线程池用法总结
    本文介绍了Spring @Async异步线程池用法总结,分享给大家,希望对大家有帮助1. TaskExecutorspring异步线程池的接口类,其实质是Java.util.concurrent.ExecutorSpring 已经实现的异常...
    99+
    2023-05-31
    async spring 线程池
  • 浅谈Laravel中使用Slack进行异常通知
    目录概述安装 maknz/slack-laravel 包配置调整 AppExceptionsHandler 类的 report 方法概述 通常,我们可以依靠用户反馈、经常查看程序日志...
    99+
    2024-04-02
  • 浅谈JS三座大山之异步和单线程
    目录单线程异步单线程 但是我们在开发中,遇到请求网络,或者定时任务的时候,如果等待网络请求结束或者定时任务结束的时候再去做其他事情,这样页面就会卡住,所以js有异步机制解决这个问题。...
    99+
    2024-04-02
  • 如何浅谈进行URL标准化的必要性
    这期内容当中小编将会给大家带来有关如何浅谈进行URL标准化的必要性,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。现在互联网越来越讲究规范化,网站的URL标准化(URL c...
    99+
    2024-04-02
  • 浅谈el-table中使用虚拟列表对对表格进行优化
    目录前言解决思路具体实现需要满足的必备条件问题前言 我们会经常使用表格,如果数据量大就直接可以分页,但是不可避免的会出现一些需要一页要展示很多条的情况,或者不用分页。 这个时候如果...
    99+
    2024-04-02
  • VUE 异步组件进阶技巧:优化代码并提升性能
    将大型组件拆分为更小的、可复用的模块。 使用 webpack 的代码分割功能动态加载组件,仅在需要时再加载。 结合路由懒加载,仅在特定路由访问时加载组件。 缓存技巧 使用 keep-alive 组件缓存已经加载的组件,避免重复加载。...
    99+
    2024-03-09
    代码拆分
  • Java编程中如何优化重定向和异步编程的同时进行资源加载?
    Java编程中,对于重定向和异步编程的处理,以及同时进行资源加载,需要注意一些优化技巧。本文将介绍如何优化这些方面,并为您提供一些演示代码。 重定向优化 重定向是指在一个URL请求中,服务器将客户端请求的URL重定向到另一个URL。在...
    99+
    2023-11-07
    重定向 异步编程 load
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作