JS中的异步与回调
问题的引出:在js中使用异步调用时,有可能会出现在异步的回调函数中设置调用之外的变量值,但在异步调用完成后去使用变量,却发现这些变量值并没有被成功设置的情况。如: google map中的地理编码,地理编码是将地址(如“1600 Amphitheatre Parkway, Mountain View, CA”)转换为地理坐标(如纬度 37.423021 和经度 -122.083739)的过程,您可以根据该地理坐标放置标记或定位地图。这个服务是异步调用,他使用geocoder进行服务查询,在查询过程中会使用返回状态码,当返回成功后我们设置其中的经度和纬度,并在以后的过程中使用这些经度和纬度,当后面的程序使用这些经度和纬度的时候发现这些经度和纬度并没有被正确地设置。
例如:
<!DOCTYPE html>
<html>
<head>
<title>Geocoding Test</title>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
6 <script type="text/javascript" src="geocode.js"></script>
7 </head>
8 <body>
9 <div id="panel"> <input id="address" type="text" value=""> <input type="button" value="Change" onclick="codeAddress()"> </div> <div id="map-canvas"></div> </body> </html>
var valLat = 0, valLng = 0;
function codeAddress() {
var geocoder = new google.maps.Geocoder();
var address = document.getElementById('address').value;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
valLat = results[0].geometry.location.lat();
valLng = results[0].geometry.location.lng();
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
alert("valLat: " + valLat + ", valLng: " + valLng);
}
整个页面有一个文本输入框和一个按扭,在文本框中输入地址“中国”,然后点击“Change”按扭
预期结果:显示出”中国“的经纬度信息
实际结果:显示的经纬度均为初始值0
分析原因:地理编码是异步服务,因此当执行geocode服务后就会继续执行后面处理经纬度的代码,此时的经纬度还没有被设置而是初始值
改进方法:将显示经纬度的代码放入地理编码的回调函数中,此时就会显示出正确的”中国“的经纬度
var valLat = 0, valLng = 0;
function codeAddress() {
var geocoder = new google.maps.Geocoder();
var address = document.getElementById('address').value;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
valLat = results[0].geometry.location.lat();
valLng = results[0].geometry.location.lng();
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
alert("valLat: " + valLat + ", valLng: " + valLng);
});
//alert("valLat: " + valLat + ", valLng: " + valLng);
}
新的问题:虽然这样可以解决异步调用显示不正确的问题,但是这样涉及到破坏封装,并造成不易于维护
改进方法:将涉及到经纬度处理的代码段使用一个函数进行调用
var valLat = 0, valLng = 0;
var count = 1; //function codeAddress() {
function codeAddress(callback) {
var geocoder = new google.maps.Geocoder();
var address = document.getElementById('address').value;
alert(address);
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
valLat = results[0].geometry.location.lat();
valLng = results[0].geometry.location.lng();
callback(valLat, valLng);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
//alert("valLat: " + valLat + ", valLng: " + valLng);
//alert("valLat: " + valLat + ", valLng: " + valLng + ", count: " + count); });
//alert("valLat: " + valLat + ", valLng: " + valLng);
}
JS中的异步与回调的更多相关文章
- JS中的异步以及事件轮询机制
一.JS为何是单线程的? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊.(在JAVA和c#中的异步 ...
- js中的异步与同步,解决由异步引起的问题
之前在项目中遇到过好多次因为异步引起的变量没有值,所以意识到了认识js中同步与异步机制的重要性 在单线程的js中,异步代码会被放入一个事件队列,等到所有其他代码执行后再执行,而不会阻塞线程. 下面是j ...
- JS中的异步
Hello,日常更新的我“浪”回来了!!! JS中有三座高山:异步和单线程.作用域和闭包.原型原型链 今天“浪”的主题是JS中的异步和单线程的问题. 主要从这三个方面入手 一.什么是异步(与同步作比较 ...
- js中的异步[Important]
js作为前端最主流的语言,主要处理页面显示变化(mutation)和异步(asynchronicity), js语言的基本要素和使用惯例的演化大都围绕着这两大主题,两者均值得总结和思考的主题, 这里先 ...
- 互联网我来了 -- 2. js中"异步/堵塞"等概念的简析
一.什么是"异步非堵塞式"? 这个名字听起来非常恶心难懂,但假设以 买内裤 这件事情来比喻运行程序的话就非常easy理解"异步非堵塞式"的涵义了. 比如你是一个 ...
- 咱们来聊聊JS中的异步,以及如何异步,菜鸟版
为什么需要异步?why?来看一段代码. 问题1: for(var i=0;i<100000;i++){ } alert('hello world!!!'); 这段代码的意思是执行100...次后 ...
- js同步、异步、回调的执行顺序以及闭包的理解
首先,记住同步第一.异步第二.回调最末的口诀 公式表达:同步=>异步=>回调 看一道经典的面试题: for (var i = 0; i < 5; i++) { setTimeout( ...
- 【第三周读书笔记】浅谈node.js中的异步回调和用js-xlsx操作Excel表格
在初步学习了node.js之后,我发现他的时序问题我一直都很模糊不清,所以我专门学习了一下这一块. 首先我们来形象地理解一下进程和线程: 进程:CPU执行任务的模块.线程:模块中的最小单元. 例如:c ...
- promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解
* promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的 ...
随机推荐
- spring冲刺第六天
昨天编写地图代码,完善地图界面,使其变得美观. 今天把地图界面初步完成,和其他团队成员的成果进行结合,整合人物和地图代码. 遇到的问题:在整合时遇到的问题比较多,今天没有整合成功.
- 第二次 作业——APP案例分析
APP案例分析 产品 网易云课堂 选择理由 网易云课堂是从大一就开始使用的一款学习软件,有海量的学习资源,很适合学生课余时间的自主学习 调研,评测 上手体验 第一次打开网易云课堂app的时候,进入的是 ...
- C++编译与链接(0)-.h与.cpp中的定义与声明
C++中有的东西需要放在可以在.h文件中定义,有的东西则必须放在.cpp文件中定义,有的东西在不同的cpp文件中的名字可以一样,而有的则不能一样 那么究竟哪些东西可在头文件中定义,声明,哪些东西又必须 ...
- Mscomm控件安装问题 License information for TMSComm not found.
操作步骤: 1.打开delphi,菜单选择compoents->import Activex control,然后选择那个mscomm32.ocx安装即可. 2.注册MScomm控件 开始- ...
- CentOS下Neo4j安装教程
本文记录一下在CentOS 6.7上,安装neo4j图数据库,本文安装的版本为neo4j-community-2.3.9-unix.tar.gz. 下载Neo4j安装包 使用wget命令获取Neo4j ...
- php 的stdClass类的简单实用
<?php $person = new stdClass(); $person->name = "yu"; $person->sex = "man&qu ...
- 用JavaScript添加选择按钮的背景颜色和juqery添加选择按钮的背景色
在项目开发中经常遇到要选择的按钮,选择完之后被选择的按钮的背景色会发生变化,表示被选择 样式图如下: 每点击一个数字,相应的背景色变为蓝色,其他的依旧是白色,先用JavaScript实现 html代码 ...
- UpdateBatch到底是怎么用的?
要使用ADOQuery的UpdateBatch函数,必须将ADOQuery的LockType属性设置成ltBatchOptimistic
- P4611 [COCI2011-2012#7] TRAMPOLIN
题目背景 有很多超级英雄:蝙蝠侠,蜘蛛侠,超人等.其中,有一位叫牛.今天他想模仿蜘蛛侠,所以他选择了一排高大的摩天楼来跳. 题目描述 具体而言,他选择了一个由 N 个摩天大楼构成的序 列,从左到右编号 ...
- 【比赛】NOIP2017 时间复杂度
恶心的模拟题,考场上犯了一堆错误,多组数据清空没清完.数组开小...民间都是50分,结果CCF90.. 考完后随便改改就过了,还好只少了10分,如果真的是50,我估计会疯掉. 因为考场的时候没写好,所 ...