JavaScript实现一个Promise队列小工具

目录
  • 摘要
  • 思考
  • 实现
  • 总结

摘要

在百度的解释中,队列是一种特殊的线性表,特殊之处在于它只允许在表的前端进行删除操作,而在表的后端进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

受这个队列结构的启发,在前端不同的业务场景中,由于一次性发起的异步请求过多,并且这些服务位于不同组件或者不同兄弟功能之间,我们无法直接对这些方法进行同步,所以需要引入队列的概念,对这些并发性的问题进行顺序处理。

思考

为什么要写一个类似于队列的功能?

我们知道,在主流的V8引擎中,JavaScript 的执行顺序都是至上而下的,引入了 ajax 之后我们能够对网页进行局部刷新,在前端领域第一次有了异步操作的概念。自此,当我们接触 Promise 之后也不在陌生于这种模式。当然,使用过 Promise 的都知道,如果是在某个单一的 js 文件中,我们完全可以通过编写一个 async 函数,通过使用 await 去实现将 Promise 函数按顺序执行的功能。

那这个队列小工具难道就是无意义的吗?作者就像一个大渣男,玩弄了一番感情轻飘飘的走了?当然不是,大家都知道在单一文件中,我们总有办法去实现这样控制异步操作的功能,那么在不同的模块、组件中,如何去实现这样的操作呢?按照这个思路,我们可以发现单纯的去写是没办法直接解决这样的异步功能同时触发的问题的,这也就是作者为什么要去些一个类似于队列的功能。

Promise 队列功能的思路在哪里?

我们先要搞明白我们想要的是一个怎样的功能呢?作者画了一个大概的需要实现功能的流程图,我们不同组件的异步请求是同时发生的,我们需要在发生之前把Promise 函数放入队列工具,再让队列工具去调度出栈和入栈的顺序,每次出栈的时候再去调用 Promise 函数发生请求。

我们可以在 js 文件中使用一个单例的概览,主要是记录入栈的顺序和对操作加锁,并且启动一个定时服务去定期检测栈中是否还有顺序,思路是很简单的,说干就干。

实现

我们新建一个 useQueue.js 文件,为了方便后续的引用。首先我们需要定义三个高级变量:

var queue = []
var locks = false
var timer = null
  • queue:记录入栈的 Promise 任务函数
  • locks:在处理出栈任务时我们需要对函数加锁,防止多次出栈
  • timer:防抖记录,跟功能 locks 主要起一个保险左右,防止出栈时重复调用函数

我们定义两个函数 handeruseQueue,导出默认函数 useQueue

/**
 * 处理任务出栈
 */
const hander = () => {}

/**
 * 入栈等待排队操作
 * @param {Promise} task
 */
const useQueue = (task) => {}

/**
 * 导出
 */
export default useQueue

当我们有任务进入时,启用 useQueue 函数,将任务放入栈中,并且设置 locks = true 进行解锁。

const useQueue = (task) => {
  queue.push(task)
  locks = true
}

这个时候,我们在单例上设置一个心跳来定期检测加锁状态,如果是解锁则触发处理函数。

// 心跳
setInterval(() => {
  locks && handler()
}, 100)

当函数 hander 被成果触发,我们需要设置一个延时器来处理防抖。先进行加锁,然后在队列中进行出栈,如果出栈为空则解锁;如果出栈不为空则调用任务,并且等待任务结束进入下一个 hander 。

const handler = () => {
  timer && clearTimeout(timer)
  timer = setTimeout(() => {
    locks = false
    const task = queue.shift()
    if (task) {
      task().then(handler)
    } else {
      locks = true
    }
  })
}

假设我们已经写了一个 vue 字典标签组件,组件内部会调用远程接口,并且再记录到某一个缓存中。如果一个页面多次使用组件,而该缓存还并未存在,那么可能会导致同时触发多个异步网络请求。这个时候就可以使用队列工具。

import useQueue from './useQueue.js'

const handleAjax = () => {
  return new Promise(resolve => {
    ...
    resolve()
  })
}

useQueue(handleAjax)

// 或者可以这样调用
useQueue(async () => {
  await handleAjax()
})

总结

Promise 队列工具实际上是通过延迟触发,来处理挂载在某一队列数据上的出栈任务,原理其实并不复杂,就是为了处理异步请求同时发生的情况。当然,这个函数可以有更多的优化方案,比如说可以添加一个优先级的参数值,根据不同优先级进行入栈操作,或者增加一个同类型排异等等。

到此这篇关于JavaScript实现一个Promise队列小工具的文章就介绍到这了,更多相关JS Promise队列内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JavaScript中 Promise 的使用技巧

    “生产代码”是可能需要一些时间来执行的代码. “消费代码”是必须等待结果的代码. Promise 是一个 JavaScript 对象,它链接生产代码和消费代码. 看一段最简单的代码: let myPromise = new Promise(function(myResolve, myReject) { // "Producing Code" (May take some time) myResolve(); // when successful myReject(); // when

  • javascript中Promise使用详解

    目录 一.首先,要知道为什么要用Promise语法? 二.接着,来了解一下回调地狱(Callback Hell) 三.最后,也是本章的重头戏,Promise的基本使用 (一) resolve函数 (二) rejected函数 (三)Promise的API 1. then 2. catch 3. finally 4. Promise.all 5. Promise.race 四.最后 前言: 做过前端开发的都知道,JavaScript是单线程语言,浏览器只分配给JS一个主线程,用来执行任务,但是每次

  • Javascript的promise,async和await的区别详解

    终于把promise, async, await的区别和联系弄清楚了,看下面代码 写法1,2是promise的写法 写法6是async和await的写法 主要看第2种写法和第6中写法即可, 第2种写法是promise的典型写法,第6中写法是async, await的典型写法 // 以下三个请求依次执行 req1 = () => { return fetch("http://example.com/api/v1/get")} req2 = () => { return fet

  • 彻底搞懂 javascript的Promise

    目录 一.为什么要引入Promise? Promise解决了什么问题? Promise有哪些具体的使用场景? 二.手写Prromise身上的方法 手写Promise.all 手写Promise.race 手写Promise.finally Promise.all和Promise.race的区别 Promise.all和Promise.race的应用场景 promise.all()的应用场景 Promise.race()的应用场景 三.Promise是如何解决串行和并行的? 什么是并行?什么是串行

  • Javascript的异步函数和Promise对象你了解吗

    目录 1.JS中的异步 1.1同步 1.2异步 1.3回调函数解决异步问题 1.4回调地狱 2.Promise对象 2.1Promise的基本使用 2.2async和await 总结 1.JS中的异步 1.1 同步 一般情况下,js的代码都是自上而下顺序运行的.例如: let res = ''; res = '获取到的结果!'; console.log(res); 结果: 很容易理解,我给res赋了新值,然后输出res.这就是js的同步执行,这里的同步,并不是一起执行的意思,而是在一个线程里顺序

  • JavaScript中Promise的执行顺序详解

    目录 前言 代码分析 then 方法何时调用? 总结 前言 最近看到一个 Promise 相关的很有意思的代码: new Promise((resolve) => { console.log(1) resolve() }).then(() => { new Promise((resolve) => { console.log(2) resolve() }).then(() => { console.log(4) }) }).then(() => { console.log(3

  • JavaScript实现一个Promise队列小工具

    目录 摘要 思考 实现 总结 摘要 在百度的解释中,队列是一种特殊的线性表,特殊之处在于它只允许在表的前端进行删除操作,而在表的后端进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为队尾,进行删除操作的端称为队头. 受这个队列结构的启发,在前端不同的业务场景中,由于一次性发起的异步请求过多,并且这些服务位于不同组件或者不同兄弟功能之间,我们无法直接对这些方法进行同步,所以需要引入队列的概念,对这些并发性的问题进行顺序处理. 思考 为什么要写一个类似于队列的功能? 我们知道

  • 使用Python制作一个打字训练小工具

    一.写在前面 说道程序员,你会想到什么呢?有人认为程序员象征着高薪,有人认为程序员都是死肥宅,还有人想到的则是996和 ICU. 别人眼中的程序员:飞快的敲击键盘.酷炫的切换屏幕.各种看不懂的字符代码. 然而现实中的程序员呢?对于很多程序员来说,没有百度和 Google 解决不了的问题,也没有 ctrl + c 和 ctrl + v 实现不了的功能. 那么身为一个程序员,要怎么让自己看起来更加"专业"呢?答案就是加快自己的打字速度了,敲的代码可能是错的,但这个13却是必须装的! 然而还

  • 使用Python制作一个数据预处理小工具(多种操作一键完成)

    在我们平常使用Python进行数据处理与分析时,在import完一大堆库之后,就是对数据进行预览,查看数据是否出现了缺失值.重复值等异常情况,并进行处理. 本文将结合GUI工具PySimpleGUI,来讲解如何制作一款属于自己的数据预处理小工具,让这个过程也能够自动化!最终效果如下 本文将分为三部分讲解: 制作GUI界面 数据处理讲解 打包与测试 主要涉及将涉及以下模块: PySimpleGUI pandas matplotlib 一.GUI界面制作 思路 老规矩,先讲思路再上代码,首先还是说一

  • Python制作一个随机抽奖小工具的实现

    目录 1. 核心功能设计 2. GUI设计与实现 3. 功能实现 3.1 读取人员名单 3.2. 随机抽奖 3.3. 保存中奖名单 3.4. GUI交互逻辑 最近在工作中面向社群玩家组织了一场活动,需要进行随机抽奖,参考之前小明大佬的案例,再结合自己的需求,做了一个简单的随机抽奖小工具. 今天我就来顺便介绍一下这个小工具的制作过程吧! 先看效果: 1. 核心功能设计 针对随机抽奖的小工具,需要可以导入参与抽奖的人员名单,然后选择不同的奖励类型进行随机抽取获奖名单并导出. 那么,简单进行需求拆解,

  • 基于Python制作一个文件去重小工具

    目录 前言 实现步骤 补充 前言 常常在下载网络素材时有很多的重复文件乱七八糟的,于是想实现一个去重的操作. 主要实现思路就是遍历出某个文件夹包括其子文件夹下面的所有文件,最后,将所有文件通过MD5函数的对比筛选出来,最后将重复的文件移除. 实现步骤 用到的第三方库都比较的常见,其中只有hashlib是用来对比文件的不是很常见.其他的都是一些比较常见的第三方库用来做辅助操作. import os # 应用文件操作 import hashlib # 文件对比操作 import logging #

  • 基于Python写一个番茄钟小工具

    目录 一.功能简述 二.使用到的主要模块 三.核心模块代码分析 1.番茄钟模块 2.音乐控制函数 3.main中的按钮部分 四.整体代码 一.功能简述 番茄钟即番茄工作法,番茄工作法是简单易行的时间管理工具,使用番茄工作法即一个番茄时间共30分钟,25分钟工作,5分钟休息: 特点一:番茄时长有三档 因为这个工具本人也是考虑到每个人情况不一样,不一定25分钟就适合自己,所以将番茄钟时长设为30min/45min/60min三档,自由选择 特点二:番茄统计功能 特点三:休息期间会自动播放放松音乐,当

  • 基于C# 写一个 Redis 数据同步小工具

    概念 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set --有序集合)和hash(哈希类型).在此基础上,redis支持各种不同方式的排序.与memcached一样,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文

  • 基于QT制作一个简易的传输文件小工具

    最近因为一个事情很恼火,因为办公需要用到企业微信,但是企业微信只能在一个电脑上登陆,所以当别人发文件给你的时候,你只能一个电脑接收,创建共享文件夹也很麻烦,每次都需要去访问,很麻烦.所以准备自己写一个文件传输小工具. 功能就是能实现文件的双向传输,即客户端能传给服务端,服务端可以传给客户端. 使用的tcp通信,其实就是发消息,但是组合数据我是借鉴了IT1995大神写的代码. 先看下效果图 可以看到既可以接受文件也可进行发送文件,只要2台电脑在统一局域网内,就可发送和接受数据. 本地文件下出现了一

  • js 创建书签小工具之理论

    我们一直在寻找增加浏览体验的方法,有的方法众所周知,有的则鲜为人知.我原本认为书签小工具属于后者,非常令人讨厌的东西.令我非常懊恼的是我发现在这个问题上我完全是错误的.它并不是令人厌烦的,而是以用户为中心的,能实现很多出色的功能,而且就像人们所预期的一样,它成为了我与浏览者以及网络交互的核心部分. 这里我想向你介绍开发书签小工具以实现一些精妙的书签的全过程.是的,书签,我们将创建不只一个书签,即使是非常小的书签.很好奇吗?我们开始吧! 究竟什么是书签小工具呢? 引用前文的话: 书签小工具是一个非

  • WordPress中使主题支持小工具以及添加插件启用函数

    让主题支持小工具 WordPress 的小工具(widget)是一大特色,它让用户自由拖动组合内容,而且任何插件和主题都可以添加一个额外的小工具,增加扩展性. 默认情况下,一个主题并不会支持小工具,需要主题开发者启用小工具功能并把小工具在相应的前台位置调用出来,这样用户才能在后台直接拖动生成侧边栏. 本文就来教你如何激活小工具功能,并且添加一个侧边栏,最后在前台显示出来. 注册侧边栏 默认的,后台外观下是没有 "小工具" 这个菜单按钮的,如果想要让他出现,就至少需要注册一个侧边栏,否则

随机推荐