JavaScript 异步编程

JavaScript 是一种单线程语言,这意味着只有一个线程可以在同一时间执行 JavaScript 代码。在 JavaScript 中,异步编程是一种编写不阻塞代码的方式,它可以在不影响页面响应的情况下执行长时间运行的操作。

JavaScript 中有几种常用的异步编程模型,如回调函数、Promise 和 async/await。

回调函数是最常用的异步编程模型,它允许在某个操作完成时调用一个函数。

Promise 是 ECMAScript 6 中引入的异步编程模型,它允许在将来的某个时间执行某个操作。

async/await 是 ECMAScript 2017 中引入的异步编程模型,它允许在同步代码中使用异步操作。

选择使用哪种异步编程模型取决于具体的场景和需求。回调函数是最简单和最基础的异步编程模型,适用于简单的异步操作。Promise 和 async/await 提供了更多的控制和灵活性,适用于复杂的异步操作。

举个例子,在浏览器中请求一个网络资源,可以使用回调函数来实现:

// 回调函数
function fetchData(callback) {
    let xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://api.example.com');
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
            callback(xhr.responseText);
        }
    };
    xhr.send();
}

fetchData(function(data) {
    console.log(data);
});

使用Promise:

// Promise
function fetchData() {
    return new Promise(function (resolve, reject) {
        let xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://api.example.com');
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                resolve(xhr.responseText);
            } else if (xhr.readyState === 4) {
                reject(xhr.status);
            }
        };
        xhr.send();
    });
}

fetchData()
    .then(function (data) {
        console.log(data);
    })
    .catch(function (error) {
        console.log(error);
    });
使用async/await:
// async/await
async function fetchData() {
    try {
        let xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://api.example.com');
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                return xhr.responseText;
            } else if (xhr.readyState === 4) {
                throw xhr.status;
            }
        };
        xhr.send();
    } catch (error) {
        console.log(error);
    }
}

let data = await fetchData();
console.log(data);
从上面的例子可以看出,使用Promise和async/await可以使代码更加简洁,并且更易于维护和阅读。 需要注意的是,使用async/await需要在一个async函数中,并且需要使用await来等待异步操作的完成。   此外,还有其他的一些异步编程方式,比如使用 setTimeout, setInterval,requestAnimationFrame 等函数来实现异步编程。 例如,使用setTimeout可以实现延迟执行某个操作:
setTimeout(() => {
    console.log('Hello World!');
}, 2000);

使用setInterval可以实现重复执行某个操作:

setInterval(() => {
    console.log('Hello World!');
}, 2000);

使用requestAnimationFrame可以实现在浏览器重绘时执行某个操作:

function animate() {
    console.log('Hello World!');
    requestAnimationFrame(animate);
}

animate();

使用setTimeout, setInterval,requestAnimationFrame 这些方法时需要注意,如果不取消定时器,它们会一直运行下去,可能会导致性能问题。

 

JavaScript 中有多种异步编程模型可供选择,可以根据项目的需求来选择最合适的方式来实现。

作者:yuzhihui
出处:http://www.cnblogs.com/yuzhihui/ 声明:欢迎任何形式的转载,但请务必注明出处!!!
本文转载于网络 如有侵权请联系删除

相关文章

  • 如何在Windows 10宿主机与Windows 98虚拟机之间共享数据

    首先按照Jerry这篇文章给windows98客户虚拟机安装VMWaretools介绍的方法,在Windows98虚拟机里安装VMWaretools.然后在windows98里安装网络服务。进入控制面板,点击网络,添加服务: 选择Microsoft网络上的文件与打印机共享,该组件安装成功之后,如下图所示:然后进入Windows98虚拟机设置,将“共享文件夹”状态设置成“总是启用”:在windows98里新建一个文件夹名叫transfer,将其设置成共享文件夹,访问类型为“完全”:然后同时打开windows10和windows98两个GUI窗口,将windows10的文件拖拽到windows98的共享文件夹即可实现文件共享的目的:

  • Java高并发基础之AQS

    引言曾经有一道比较比较经典的面试题“你能够说说java的并发包下面有哪些常见的类?”大多数人应该都可以说出CountDownLatch、CyclicBarrier、Sempahore多线程并发三大利器。这三大利器都是通过AbstractQueuedSynchronizer抽象类(下面简写AQS)来实现的,所以学习三大利器之前我们有必要先来学习下AQS。★AQS是一种提供了原子式管理同步状态、阻塞和唤醒线程功能以及队列模型的简单框架 ”AQS结构说到同步我们如何来保证同步?大家第一印象肯定是加锁了,说到锁的话大家肯定首先会想到的是Synchronized。Synchronized大家应该基本上都会使用,加锁和释放锁都是jvm来帮我们实现的,我们只需要简单的加个Synchronized关键字就可以了。用起来超级方便。但是有没有一种情况我们设置一个锁的超时时间Synchronized就有点实现不了,这时候我们就可以用ReentrantLock来实现,ReentrantLock是通过aqs来实现的,今天我们就通过ReentrantLock来学习一下aqs。CAS&&公平锁和非公

  • 聊聊dubbo-go-proxy的loggerFilter

    序本文主要研究一下dubbo-go-proxy的loggerFilterloggerFilterdubbo-go-proxy/pkg/filter/logger/logger.go//nolint funcInit(){ extension.SetFilterFunc(constant.LoggerFilter,loggerFilterFunc()) } funcloggerFilterFunc()context.FilterFunc{ returnNew().Do() } //loggerFilterisafilterforsimplelogger. typeloggerFilterstruct{ } //Newcreateloggerfilter. funcNew()filter.Filter{ return&loggerFilter{} }复制loggerFilter的Init方法往extension设置了loggerFilterFunc,该context.FilterFunc执行loggerFilter的Do方法 Dodubbo-go-proxy/pkg/filt

  • nor flash之写保护开销

    背景之前有介绍过写保护,这里就不赘述了,可参考:https://www.cnblogs.com/zqb-all/p/12182920.html但没有谈到开销,今天有同事问起,便记录一下性能不考虑写保护的nor性能评估及实测,可参考:https://www.cnblogs.com/gmpy/p/12011436.htmlbp保护的开销bp保护,一般都需要写StatusRegister,这种寄存器是一般是non-volatile,即非易失性,也就是写入后掉电值不会丢失重置,就像写入了flash的数据一般。这个特性也决定了,其编程时间要长一些。一般是ms级别的。放两家flash的规格书截图供参考,请看其中的tw值:ms级别的开销意味着,如果在每次写入之前解保护,写入之后恢复保护,会对写性能造成很大的影响。独立块保护的开销独立块保护,启用功能时需要写StatusRegister,启用后就不再需要操作StatusRegister了。每次发送的解保护命令和保护命令,导致的状态改变是volatile,即易失性的,掉电后就会被清空,上电时flash总是处于全保护的状态。每个block的保护状态标记,其

  • 小程序 下拉刷新 上拉加载

    微信小程序下拉刷新上拉加载,简单方便,易于上手。 1.首先上list.wxml代码<!--pages/list/list.wxml--> <viewclass="list-container"> <viewclass="header"> </view> <viewclass="doc-item"wx:for="{{dataSource}}"wx:for-item="item"wx:key="{{item.id}}"bindtap='bindViewTap'data-url="{{item.url}}"data-name="{{item.name}}"> <text>{{item.title}}</text> <viewclass='item-info'> <text>{{item.

  • Wolfram 神器秒杀高考数学试题

    曹亚云 甘肃省中学数学教师,致力于将WolframMathematica应用于中学数学教育。█Wolfram|Alpha结果由Wolfram提供2017年普通高等学校招生全国统一考试数学(理)(北京卷)In[1]:=Reduce[{-2<x<1,x<-1\[Or]x>3},x] Out[1]=-2<x<-1复制In[2]:=z=(1-I)(a+I);Reduce[{Re[z]<0,Im[z]>0,a\[Element]Reals},a] Out[3]=a<-1复制In[4]:=k=0;s=1;While[k<3,k=k+1;s=(s+1)/s];s Out[4]=5/3复制In[5]:=MaxValue[{x+2y,x<=3,x+y>=2,y<=x},{x,y},Reals] Out[5]=9复制In[6]:=f[x_]=3^x-(1/3)^x;FullSimplify[{f[-x]==-f[x],f[-x]==f[x]}] Out[7]={True,Sinh[xLog[3]]==0}复制由计算可知,f(x)

  • 其它网络下的容器加入mynet网络,实现一个容器两个ip地址

    上篇讲到创建自定义网络,我创建了mynet网络,并指定了网关和子网地址。在上篇结尾呢,我抛出了一个问题:其它网络下的容器可以直接访问mynet网络下的容器吗?今天就让我们一块看下怎么实现容器互联。其它网络下的容器加入mynet网络,实现一个容器两个ip地址网络集群先创建test-network网络:dockernetworkcreatetest-network再运行centos01容器并加入到test-network网络下dockerrun-it-P--namecentos01--nettest-networkcentoscentos01容器已经加入在test-network网络下了centos01加入mynet网络root@---~]#dockernetworkconnectmynetcentos01复制查看mynet网络dockernetworkls[root@---~]#dockernetworkls NETWORKIDNAMEDRIVERSCOPE feafa30d4051bridgebridgelocal e8bf4fced9e2hosthostlocal 0096a971f

  • Variable @primary-color-hover is undefined

    antd安装启动后报错Variable@primary-color-hoverisundefined 报错前package.json中依赖版本信息: "dependencies":{ ... "@ant-design/pro-form":"^1.15.1", "@ant-design/pro-layout":"^6.15.0", "@ant-design/pro-table":"^2.27.1", "antd":"4.9.4", }, 复制 错误原因:@ant-design/pro-layout、@ant-design/pro-table包版本导致的,锁定为固定版本就可以了 "dependencies":{ ... "@ant-design/pro-form":"^1.15.1", "@ant-design/pro-layout":"6.15.0", "@ant-design/pro-table":"2.27.1", "antd":"4.9.4", }, [相关错误issue](https://github.com/ant-design/pro-components/issues/4

  • 【译】Spring的@EnableCaching注解

    Spring的@EnableCaching注解 @EnableCaching注解是springframework中的注解驱动的缓存管理功能。自spring版本3.1起加入了该注解。如果你使用了这个注解,那么你就不需要在XML文件中配置cachemanager了。 当你在配置类(@Configuration)上使用@EnableCaching注解时,会触发一个postprocessor,这会扫描每一个springbean,查看是否已经存在注解对应的缓存。如果找到了,就会自动创建一个代理拦截方法调用,使用缓存的bean执行处理。 如果你对缓存感兴趣并想了解更多,请阅读springcaching.本文会帮助你了解如何使用@EnableCaching注解。 接下来的例子演示了@EnableCaching的用法。在代码中,我缓存了Book类找那个的方法。 代码   //Book.java   importorg.springframework.cache.annotation.Cacheable;   publicclassBook{ &

  • 修复SSL/TLS协议信息泄露漏洞

    一.第一种解决方法:升级opensslOpenSSL1.0.2用户应升级到1.0.2iOpenSSL1.0.1用户应升级到1.0.1u openssl最新版本是1.1.1系列,且是TLS版本 查看版本 opensslversion 复制    二.第二种解决方法nginx禁用des和3des加密 #配置加密算法 ssl_ciphers"HIGH:!aNULL:!MD5:!DES:!3DES"; 复制    三.验证漏洞是否已修复 nmap-sV--scriptssl-cert,ssl-enum-ciphers-p443服务IP或域名|grepDES复制 如无输出,则表明已修复

  • 调参必备---GridSearch网格搜索

    什么是GridSearch网格搜索? GridSearch:一种调参手段;穷举搜索:在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。其原理就像是在数组里找最大值。(为什么叫网格搜索?以有两个参数的模型为例,参数a有3种可能,参数b有4种可能,把所有可能性列出来,可以表示成一个3*4的表格,其中每个cell就是一个网格,循环过程就像是在每个网格里遍历、搜索,所以叫gridsearch) SimpleGridSearch:简单的网格搜索 以2个参数的调优过程为例: fromsklearn.datasetsimportload_iris fromsklearn.svmimportSVC fromsklearn.model_selectionimporttrain_test_split iris=load_iris() X_train,X_test,y_train,y_test=train_test_split(iris.data,iris.target,random_state=0) print("Sizeoftrainingset:{}sizeoft

  • 由于不能随便改路径,所以写在这里

    exportLD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64:$LD_LIBRARY_PATHexportPATH=/usr/local/cuda-8.0/bin:$PATH exportLD_LIBRARY_PATH=/root/anaconda2/envs/LTproto261/lib复制 exportPYTHONPATH=/dev/LT/SegNet/caffe-segnet/python:$PYTHONPATH 本博客专注于错误锦集,在作死的边缘试探

  • MongoDB用户与权限管理

    read 允许用户读取指定数据库 readWrite 允许用户读写指定数据库 dbAdmin 允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile userAdmin 允许用户向system.users集合写入,可以在指定数据库里创建、删除和管理用户 clusterAdmin 只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限 readAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读权限 readWriteAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读写权限 userAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的userAdmin权限 dbAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限 root 只在admin数据库中可用。超级账号,超级权限 创建管理用户

  • Radmin自动连接 c#版 带源码

      实现原理:1.利用radminview自带命令              2.大漠绑定插件. 附图:     源码下载:https://files.cnblogs.com/eastday/Radmin%E8%87%AA%E5%8A%A8%E7%99%BB%E5%BD%95.rar

  • PapaMelon #5 设计单向链表

    题目链接 设计单向链表 题解 就是一个基础的数据结构题,选自PapaMelon系统算法课程-基础版,目的是为了让我们熟悉单向链表的各种操作,包括:插入,删除,倒转,遍历 #include<iostream> #include<cstdio> #include<vector> #include<string> #include<algorithm> #include<cassert> usingnamespacestd; constvector<string>OP={ "PUSH_FRONT","POP_FRONT","INSERT","CONTAINS", "REMOVE","REVERSE","FOR_EACH"}; structNode{ intval; Node*next; Node():val(-1),next(nullptr){} Node(intx):val(x),next(nullptr){} }; structList{ Node*head; List(){ head=

  • [LeetCode82]Remove Duplicates from Sorted List II

    题目: Givenasortedlinkedlist,deleteallnodesthathaveduplicatenumbers,leavingonly distinct numbersfromtheoriginallist. Forexample,Given 1->2->3->3->4->4->5,return 1->2->5.Given 1->1->1->2->3,return 2->3. 分类:LinkedList 代码:维护两个指针ptr,pre 1/** 2*Definitionforsingly-linkedlist. 3*structListNode{ 4*intval; 5*ListNode*next; 6*ListNode(intx):val(x),next(NULL){} 7*}; 8*/ 9classSolution{ 10public: 11ListNode*deleteDuplicates(ListNode*head){

  • 多片PCF8574扩展树莓派IO

    这里选择了使用3片PCF8574扩展,可以拓展出24个双向IO口。 如果有不了解,可参考我前边的几篇文章: 树莓派i2c配置 树莓派安装WiringPi库 PCF8574扩展树莓派io口    正面接线图:   反面焊点图:       (注意:PCF8574芯片的A0A1A2引脚电平状态,这里的接法三片PCF8574的地址分别为0x200x210x22,实际可根据自己的需要进行调整。)   连接好芯片后,用 i2cdetect 工具查看芯片识别状态 sudoi2cdetect-y1复制 如果按我的地址选择方案,正常情况下会显示如下: 0123456789abcdef 00:-------------------------- 10:-------------------------------- 20:202122-------------------------- 30:-------------------------------- 40:-----------

  • Zookeeper系列五:Master选举、ZK高级特性:基本模型

    一、Master选举 1.master选举原理: 有多个master,每次只能有一个master负责主要的工作,其他的master作为备份,同时对负责工作的master进行监听,一旦负责工作的master挂掉了,其他的master就会收到监听的事件,从而去抢夺负责工作的权利,其他没有争夺到负责主要工作的master转而去监听负责工作的新master。 本质其实是利用zookeeper的临时节点的特性:临时节点随着会话的消亡二消亡,同一个临时节点只能创建一个,创建失败的节点(从master)对创建成功节点(主master)进行监控,一旦创建成功的节点(主master)会话消失,之前创建失败的节点(从master)就会监听到去抢夺创建临时节点 2.代码实现-两个tomcat模拟master选举 2.1准备工作: 1)首先在新建一个maven项目ZK-Demo,然后在pom.xml里面引入zk的依赖 <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookee

  • 前端项目部署在tomcat

    需在server.xml中进行配置 <Hostname="localhost"appBase="webapps"  unpackWARs="true"autoDeploy="true">   <ValveclassName="org.apache.catalina.valves.AccessLogValve"directory="logs"   prefix="localhost_access_log"suffix=".txt"   pattern="%h%l%u%t&quot;%r&quot;%s%b"/>     <Contextpath="/chat"docBase="../webapps/irobot.war"reloadable="true"source="org.eclipse.jst.jee.server:tsj-spring"/>     <ContextdocBase="D:\aaaaaaaaaaaaa\apache-tomcat-8.5.51\webapps\HCS_ROBOT"path

  • C语言I博客作业07

    这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 “https://edu.cnblogs.com/campus/zswxy/SE2019-1/homework/9931” 我在这个课程的目标是 将想法在计算机上实现 这个作业在那个具体方面帮助我实现目标 提供联系材料 参考文献 【C语言程序设计】和【C语言程序设计实验与习题指导】 1.PTA实验作业 7-10计算天数(15分) 输入在一行中按照格式“yyyy/mm/dd”(即“年/月/日”)给出日期。注意:闰年的判别条件是该年年份能被4整除但不能被100整除、或者能被400整除。闰年的2月有29天。 1.1.1数据处理 数据表达:用有y,m,d,来表示年月日;n来表示第几天; 数据处理: 输入:年月日 if判断y是否为闰年 switch case(1-12)d/m1+d/m1+e+d/m1+e+d+m3/...... 输出:最终天数 1.1.2代码截图 1.1.3造测试数据 输入数据|输出数据|说明| -|- 2009/03/02|61|题目数据| 2000/03/02|62|题目数据|

  • Struts2文件上传

    平时都是直接在action中按照struts2定义的格式来接流,最近看到华为技术人员调用struts2底层方法对文件流做了封装,感觉有用赶紧记了下来  Java代码         publicvoidpreExecute() { if(httpServletRequestinstanceofMultiPartRequestWrapper) { MultiPartRequestWrapperrequestWrapper=(MultiPartRequestWrapper)httpServletRequest; Enumeration<String>parameterNames=requestWrapper.getFileParameterNames(); while(parameterNames.hasMoreElements()) { @SuppressWarnings("unused") StringparamterName=parameterNames.nextElement(); File[]file

相关推荐

推荐阅读