这里展示一个操作场景:需要对数据进行异步处理,但这次操作可能会失败,所以需要定期对数据进行再次处理,直至处理成功。

实现:手动触发的处理以及定期触发的处理,是相同的,即可以抽取出来成一个公共函数,定期操作使用setInterval实现,对应以下的示例代码:

function otherAsyncApiCall(n){
return new Promise(resolve => setTimeout(resolve, n * 1000))
} // 抽取出公共的数据操作函数
async function dataOperation(data){
console.log(data + "读取数据库,并操作");
// 模拟数据处理中的异步操作
await otherAsyncApiCall(3);
console.log(data + "操作结果写入数据库");
} async function run(){
// 开启定期操作,每5秒操作一次
setInterval(()=>{
dataOperation("定期触发 -");
},5000); await dataOperation("1手动触发 -");
await dataOperation("2手动触发 -");
}
run();

执行结果:

1手动触发 -读取数据库,并操作
1手动触发 -操作结果写入数据库
2手动触发 -读取数据库,并操作
定期触发 -
读取数据库,并操作
2手动触发 -操作结果写入数据库
定期触发 -操作结果写入数据库

红色标记中出现一个严重问题:出现重复操作和写数据库。

解决办法是换一种实现思路:

维护一个全局的消息队列,添加一个额外的定时操作去定期消费队列中的消息,原有的定时操作以及手动触发都换成往队列中写数据,而不实际操作数据。这样一来,实际消费消息的地方只有一个,就能避免以上问题了。

简易版的消息队列实现:

+function(){
const queue = [];
const handlerMap = {};
const gap = 5 * 1000; window.messageQueue = {
put(type, data){
queue.push({type, data})
},
get(){
return queue.shift();
}, // 要求传入的fn必须返回一个Promise,告知执行的完成情况
handle(type, fn){
handlerMap[type] = fn;
}
};
window.messageQueue.MSG_TYPE = {
UPLOAD_IMG: 1,
}; async function eatMsg(){
const target = queue.shift();
if(!target){
return;
}
const handlerFn = handlerMap[target.type];
return handlerFn && handlerFn(target.data);
} function range(){
const next = ()=> setTimeout(range, gap); // 保证循环不会断
eatMsg().then(next).catch(next);
} range();
}();

ps:setInterval的循环中,不会受到await的影响而延迟,如以下代码中数据操作还没处理完,就会马上开始下一次触发,所以需要保证两次触发的时间间隔要大于实际的数据处理时间,才是安全的。

    setInterval(async ()=>{
// 这里的异步操作是三秒
await dataOperation("定期触发 -");
},1000);

JS异步与同步的更多相关文章

  1. js 异步转同步

    在项目中有些逻辑或者请求依赖另一个异步请求,大家常用的方法是回调函数.现在有个高大上的解决方案:await async . async 是“异步”的简写,而 await 可以认为是 async wai ...

  2. 【Mocha.js 101】同步、异步与 Promise

    前情提要 在上一篇文章<[Mocha.js 101]Mocha 入门指南>中,我们提到了如何用 Mocha.js 进行前端自动化测试,并做了几个简单的例子来体验 Mocha.js 给我们带 ...

  3. 关于js中的同步和异步

    最近看到前端面试问到js中的同步和异步,这个问题该怎么回答? 梳理一下,js对于异步的处理,很多人的第一反应是ajax,这只能说是对了一半. 1.个人觉得,js中,最基础的异步是setTimeout和 ...

  4. 似是而非的JS - 异步调用可以转化为同步调用吗?

    源起 小飞是一名刚入行前端不久的新人,因为进到了某个大公司,俨然成为了学弟学妹眼中'大神',大家遇到js问题都喜欢问他,这不,此时他的qq弹出了这样一条消息 "hi,大神在吗?我有个问题想问 ...

  5. js中的异步与同步,解决由异步引起的问题

    之前在项目中遇到过好多次因为异步引起的变量没有值,所以意识到了认识js中同步与异步机制的重要性 在单线程的js中,异步代码会被放入一个事件队列,等到所有其他代码执行后再执行,而不会阻塞线程. 下面是j ...

  6. JS异步解决方案之概念理解-----------阻塞和非阻塞,同步和异步,并发和并行,单线程和多线程

    首先记住一句话,JS是单线程的. 单线程意味着什么?单线程意味着 它不能依靠自己实现异步. JS实现的异步,往往都是靠 浏览器.Node 的机制(事件驱动.回调)实现的. 下面让我这个单身狗 以谈恋爱 ...

  7. JS中的同步异步问题

    <script> /* * JS 是单线程 * 同步 异步 * 常见的异步 * 1.定时器 * 2.事件绑定 * 3.ajax请求(一般的都是异步) * 4.回调函数也可以理解成 异步 * ...

  8. JS中的同步异步编程

    首先我们先看看同步与异步的定义,及浏览器的执行机制,方便我们更好地理解同步异步编程. 浏览器是多线程的,JS是单线程的(浏览器只分配一个线程来执行JS)   进程大线程小:一个进程中包含多个线程,例如 ...

  9. Node.js模拟发起http请求从异步转同步的5种方法

    使用Node.js模拟发起http请求很常用的,但是由于Node模块(原生和第三方库)提供里面的方法都是异步,对于很多场景下应用很麻烦,不如同步来的方便.下面总结了几个常见的库API从异步转同步的几种 ...

随机推荐

  1. 原来rollup这么简单之插件篇

    大家好,我是小雨小雨,致力于分享有趣的.实用的技术文章. 内容分为翻译和原创,如果有问题,欢迎随时评论或私信,希望和大家一起进步. 大家的支持是我创作的动力. 计划 rollup系列打算一章一章的放出 ...

  2. Ubuntu 修改$PS1 自定义命令提示符

    文章更新于:2020-03-25 文章目录 一.自定义命令提示符 1.可修改的是那部分? 2.修改 $PS1 变量 3.$PS1 变量格式 4.如何修改背景颜色 5.修改字体 二.Enjoy! 一.自 ...

  3. .net core 实现excel 和 word 的在线预览

    最新在搞文件的在线预览,网上很多免费的方案都需要是电脑安装office的,这要就很麻烦:收费的插件又太贵了. 不过还是找到一款相对好用的免费在线预览插件. 直接在nuget上搜索ce.office.e ...

  4. 使用webview查找元素,appium查找web页面元素

    9 webview查找元素 9.1 webview 简介 WebView是android中一个非常重要的控件,它的作用是用来展示一个web页面.它使用的内核是webkit引擎,4.4版本之后,直接使用 ...

  5. RESTful API设计的点

    RESTful API 前言 一直在使用RESTful API,但是好像概念还是很模糊的,总结下使用到的点 设计的规范 协议 API与用户的通信协议,总是使用HTTPs协议. 域名 应该尽量将API部 ...

  6. 动态网页D-html

    BOM(Browser Object Model)浏览器对象模型 window对象(window – 代表浏览器中打开的一个窗口) 1.alert()方法 – 定义一个消息对话框 window.ale ...

  7. SpringBoot实现图片上传demo&Nginx进行代理显示

    公司项目需要一个图片上传的功能,就图片能上传到服务器(公司用的windows服务器),然后nginx能进行代理访问到就行了,先简单介绍一下nginx,然后再来实现功能. 一.nginx简介 Nginx ...

  8. 如何防止CDN防护被绕过

    当攻击者发现目标站点存在CDN防护的时候,会尝试通过查找站点的真实IP,从而绕过CDN防护.我们来看一个比较常见的基于公有云的高可用架构,如下:CDN(入口层)->WAF(应用层防护)-> ...

  9. Oracle数据库排序后分页查询数据错误问题解决

    一.问题描述:根据更新时间倒序排序然后分页查询数据,但是点击分页操作的时候,会出现数据重复看似没有操作的情况 二.问题错误原因分析 分页查询的SQL语句: select * FROM (select ...

  10. Flutter 开发填坑指南

    引言 第一次在使用Flutter是在Ubuntu机器上,但是因为Android Studio还有Sdk配置问题,flutter doctor总是在这一步报错...最近又在win10上配了一下环境(真香 ...