JS异步与同步
这里展示一个操作场景:需要对数据进行异步处理,但这次操作可能会失败,所以需要定期对数据进行再次处理,直至处理成功。
实现:手动触发的处理以及定期触发的处理,是相同的,即可以抽取出来成一个公共函数,定期操作使用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异步与同步的更多相关文章
- js 异步转同步
在项目中有些逻辑或者请求依赖另一个异步请求,大家常用的方法是回调函数.现在有个高大上的解决方案:await async . async 是“异步”的简写,而 await 可以认为是 async wai ...
- 【Mocha.js 101】同步、异步与 Promise
前情提要 在上一篇文章<[Mocha.js 101]Mocha 入门指南>中,我们提到了如何用 Mocha.js 进行前端自动化测试,并做了几个简单的例子来体验 Mocha.js 给我们带 ...
- 关于js中的同步和异步
最近看到前端面试问到js中的同步和异步,这个问题该怎么回答? 梳理一下,js对于异步的处理,很多人的第一反应是ajax,这只能说是对了一半. 1.个人觉得,js中,最基础的异步是setTimeout和 ...
- 似是而非的JS - 异步调用可以转化为同步调用吗?
源起 小飞是一名刚入行前端不久的新人,因为进到了某个大公司,俨然成为了学弟学妹眼中'大神',大家遇到js问题都喜欢问他,这不,此时他的qq弹出了这样一条消息 "hi,大神在吗?我有个问题想问 ...
- js中的异步与同步,解决由异步引起的问题
之前在项目中遇到过好多次因为异步引起的变量没有值,所以意识到了认识js中同步与异步机制的重要性 在单线程的js中,异步代码会被放入一个事件队列,等到所有其他代码执行后再执行,而不会阻塞线程. 下面是j ...
- JS异步解决方案之概念理解-----------阻塞和非阻塞,同步和异步,并发和并行,单线程和多线程
首先记住一句话,JS是单线程的. 单线程意味着什么?单线程意味着 它不能依靠自己实现异步. JS实现的异步,往往都是靠 浏览器.Node 的机制(事件驱动.回调)实现的. 下面让我这个单身狗 以谈恋爱 ...
- JS中的同步异步问题
<script> /* * JS 是单线程 * 同步 异步 * 常见的异步 * 1.定时器 * 2.事件绑定 * 3.ajax请求(一般的都是异步) * 4.回调函数也可以理解成 异步 * ...
- JS中的同步异步编程
首先我们先看看同步与异步的定义,及浏览器的执行机制,方便我们更好地理解同步异步编程. 浏览器是多线程的,JS是单线程的(浏览器只分配一个线程来执行JS) 进程大线程小:一个进程中包含多个线程,例如 ...
- Node.js模拟发起http请求从异步转同步的5种方法
使用Node.js模拟发起http请求很常用的,但是由于Node模块(原生和第三方库)提供里面的方法都是异步,对于很多场景下应用很麻烦,不如同步来的方便.下面总结了几个常见的库API从异步转同步的几种 ...
随机推荐
- Spring(三):bean的自动装配
Bean的自动装配 自动装配是Spring满足bean依赖的一种方式. Spring会在上下文中自动寻找,并自动给bean装配属性 Spring中三种装配方式 在xml中显式的配置. 在java中显式 ...
- C++ namespace 命名空间
namespace即"命名空间",也称"名称空间" 那么这个 "名称空间" 是干啥的呢? 我们都知道,C/C++中的作用域可以由一个符号 { ...
- webstorm 永久激活方法
打开终端,执行: cd /etc/ sudo vim hosts 在最后一行加上: 0.0.0.0 account.jetbrains.com 打开webstorm,选择Activation Code ...
- 个人项目 wc.exe
GitHub地址:https://github.com/oAiuo/wordCount 一.题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行单元测试. ...
- 2、使用断言(json assertion)
1.假设现在有一个服务端的返回数据(需要测试的)为:HTTP/1.1 200 OK,要测试的响应字段勾选Response Headers,模式匹配规则选择Substring,把该响应断言命名为Http ...
- Git应用详解第七讲:Git refspec与远程分支的重要操作
前言 前情提要:Git应用详解第六讲:Git协作与Git pull常见问题 这一节来介绍本地仓库与远程仓库的分支映射关系:git refspec.彻底弄清楚本地仓库到底是如何与远程仓库进行联系的. 一 ...
- replace into 影响行数
replace into 影响行数,谈起影响行数,先理解replace into 原理:其是先到表里通过一定规则(单主键或复合主键或唯一索引)找到记录,并且删除,然后在insert into 记录,即 ...
- FastAPI框架
目录 FastAPI框架 安装 基本使用 模版渲染 安装jinja2 基本使用 form表单数据交互 基本数据 文件交互 静态文件配置 FastAPI框架 该框架的速度(天然支持异步)比一般的djan ...
- Android UIAutomator自动化测试
描述:UiAutomator接口丰富易用,可以支持所有Android事件操作,事件操作不依赖于控件坐标,可以通过断言和截图验证正确性,非常适合做UI测试. UIAutomator不需要测试人员了解代码 ...
- 文件密码忘记了怎么办,教你如何使用Python破解密码
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:轻松学编程小梁 PS:如有需要Python学习资料的小伙伴可以加点击下 ...