问题的引出:在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中的异步与回调的更多相关文章

  1. JS中的异步以及事件轮询机制

    一.JS为何是单线程的? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊.(在JAVA和c#中的异步 ...

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

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

  3. JS中的异步

    Hello,日常更新的我“浪”回来了!!! JS中有三座高山:异步和单线程.作用域和闭包.原型原型链 今天“浪”的主题是JS中的异步和单线程的问题. 主要从这三个方面入手 一.什么是异步(与同步作比较 ...

  4. js中的异步[Important]

    js作为前端最主流的语言,主要处理页面显示变化(mutation)和异步(asynchronicity), js语言的基本要素和使用惯例的演化大都围绕着这两大主题,两者均值得总结和思考的主题, 这里先 ...

  5. 互联网我来了 -- 2. js中&quot;异步/堵塞&quot;等概念的简析

    一.什么是"异步非堵塞式"? 这个名字听起来非常恶心难懂,但假设以 买内裤 这件事情来比喻运行程序的话就非常easy理解"异步非堵塞式"的涵义了. 比如你是一个 ...

  6. 咱们来聊聊JS中的异步,以及如何异步,菜鸟版

    为什么需要异步?why?来看一段代码. 问题1: for(var i=0;i<100000;i++){ } alert('hello world!!!'); 这段代码的意思是执行100...次后 ...

  7. js同步、异步、回调的执行顺序以及闭包的理解

    首先,记住同步第一.异步第二.回调最末的口诀 公式表达:同步=>异步=>回调 看一道经典的面试题: for (var i = 0; i < 5; i++) { setTimeout( ...

  8. 【第三周读书笔记】浅谈node.js中的异步回调和用js-xlsx操作Excel表格

    在初步学习了node.js之后,我发现他的时序问题我一直都很模糊不清,所以我专门学习了一下这一块. 首先我们来形象地理解一下进程和线程: 进程:CPU执行任务的模块.线程:模块中的最小单元. 例如:c ...

  9. promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解

    * promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的 ...

随机推荐

  1. 使用Git进行代码管理心得------------个人练习

    一.在github.com上的操作   今天我们实践课程学习了用Git进行代码版本,使用github进行代码托管,我和队友在官网上创建了自己的Organization,将Auto CS fork到了小 ...

  2. DPDK flow_classify 源码阅读

    代码部分 /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2017 Intel Corporation */ #include < ...

  3. SQL Server 2008 存储过程示例

    出处:http://www.jb51.net/article/54730.htm --有输入参数的存储过程-- create proc GetComment (@commentid int) as s ...

  4. 关于mybatis的思考(2)——mybatis映射文件的深入理解

    1.配置文件 mybatis进行持久化操作是以SqlSessionFactory对象为基础的,这个对象是整个数据库映射关系经过编译后的内存镜像. InputStream inputStream = R ...

  5. 关于VS2005中C#代码用F12转到定义时,总是显示从元数据的问题

    元数据是:NET 程序集中的标记信息. 是在代码中选择了转到定义时候给定位的吧.因为没有找到源代码,VS通过反射读取元数据中的信息生成了那个. 解决方法: 1. 要把项目先添加到解决方案中. 2. 再 ...

  6. 性能分析_linux服务器CPU_中断

    中断 1.  指标范围 1.1  Interrupt rate 应该与cpu利用率结合分析,如果cpu利用率在合理范围内,大量的中断也是可以接受的.一个巨大的中断值,同时伴随着缓慢的系统性能表现,指示 ...

  7. 如何修改eclipse下注释的颜色

    修改注释颜色:window -- preferences -- java --editor --syntax coloring -- comments 中的前两个就是修改注释颜色的.点击右边的colo ...

  8. vue使用axios发送数据请求

    本文章是基于vue-cli脚手架下开发 1.安装 npm install axios --s npm install vue-axios --s 2.使用.在index.js中(渲染App组件的那个j ...

  9. centos7防火墙操作

    启动: systemctl start firewalld 关闭: systemctl stop firewalld 查看状态: systemctl status firewalld 开机禁用 : s ...

  10. Atcoder arc080E Young Maids(线段树+优先队列)

    给出一个n排列,每次可以选择相邻的两个数字放在新的排列首部,问最后形成的新的排列字典序最小是? 考虑新排列的第一个数字,则应是下标为奇数的最小数,下标不妨设为i.第二个数字应该下标大于i且为偶数的最小 ...