问题的引出:在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. Beta Scrum Day 2 — 听说

    听说

  2. git 提交本地文件,删除文件夹,修改文件等

    1. 下载git工具包 链接: https://git-scm.com/download/win 2. 右键打开git bash 登陆到自己的github账户 $ git config --globa ...

  3. 浅谈Java中的Hashmap

    HashMap:   java.lang.Object ∟ java.util.AbstractMap<K,V> ∟ java.util.HashMap<K,V> 类型参数: ...

  4. Navicat Premium 连接Oracle 数据库

    昨天开始工作的时候听同事说:Navicat可以连各种数据库,包括Oracle,头一次听说!!!很是尴尬.现在记录一下怎么用Navicat连接Oracle.最重要的是,Navicat只支持32的Orac ...

  5. 16_常用API_第16天(正则表达式、Date、DateFormat、Calendar)_讲义

    今日内容介绍 1.正则表达式的定义及使用 2.Date类的用法 3.Calendar类的用法 ==========================================第一阶段======= ...

  6. jsp与Ajax技术

    Ajax 是Asynchronous Javascript and XML的缩写,异步的JavaScript和xml.Ajax是由JavaScript.XML.CSS.DOM等多种已有技术的结合,它可 ...

  7. Codeforces 449B_Jzzhu and Cities

    给一个无向图,外加一些特殊的连接原点的无向边.在不改变原点与所有点的最短路的情况下,最多可以删除多少条特殊边? 首先我们把所有的边夹杂在一起.spfa跑出与所有点的最短路. 接下来我们通过一次bfs来 ...

  8. [Offer收割]编程练习赛23-freeloop

    A. H国的身份证号码I dfs裸题. 时间复杂度\(O(n^k)\). #include <bits/stdc++.h> #define FOR(i,a,b) for (int i=a; ...

  9. 每日一问(如何在List中加入、设置、获取和删除其中的元素?)

    作为集合接口的一部分,对List接口所做的操作,最常见的就是增删查改了.这里总结下JAVA 中List接口及实现该接口的类实现这些操作的方法. 一.增加新的元素的方法 在Collection接口中定义 ...

  10. Theme Section HDU - 4763(些许暴力)

    题意: 求出最长公共前后缀 不能重叠  而且 这个前后缀 在串的中间也要出现一次 解析: 再明确一次next数组的意思:完全匹配的最长前后缀长度 求一遍next 然后暴力枚举就好了 #include ...