异步操作应该是以前学习 ajax 时才被明确提及,就目前的理解,同步就是同一时间只能做一件事,如果使用 ajax同步模式,则代码会卡在 xhr.send() 这里,只有请求响应的过程全部完成了才会执行下面的代码,而异步操作的话代码的执行不会等待,会直接一溜烟地从上到下执行完

js 中的异步操作:

❶ 定时器

❷ 事件绑定

❸ ajax异步模式

❹ 回调函数

如何获取一个函数中异步操作的结果,例如调用函数 fn() 得到内部变量 data 的值

  1. function fn() {
  2.   setTimeout(function () {
  3.   var data = 'Hi'
  4. },1000)
      console.log(data)
  5. }
  6. fn()

由于定时器 1 秒后才执行,但代码早已执行到了 console,所以输出结果为 data is not defined

  1. function fn() {
  2. setTimeout(function () {
  3. var data = 'Hi'
  4. return data
  5. },1000)
  6. }
  7. console.log(fn())

fn 函数没有返回值,所以输出结果为 undefined

return 是定时器里的那个 function 进行 return 的,与 fn 无关

  1. var data = '^_^'
  2. function fn() {
  3. setTimeout(function () {
  4. data = 'Hi'
  5. },1000)
  6. return data
  7. }
  8. console.log(fn())

定时器是异步的,所以代码不等待,会直接执行到 return,赋值操作没有执行,所以结果为 ^_^

正确方式

如果需要获取一个函数中异步操作的结果,则必须通过回调函数来获取

  1. function fn(callback) {
  2. //传入一个函数,就相当于在这创建了一个叫callback的函数
  3. //var callback = function (data) { console.log(data) }
  4. setTimeout(function () {
  5. var data = 'Hi'
  6. callback(data)
  7. },1000)
  8. }
  9. fn(function (data) {
  10. console.log(data)
  11. })

关键的一步是在定时器内调用 callback ,前面的情况之所以拿不到数据是因为,data 变量在定时器内定义,函数不等定时器里的 function 执行就立马想拿到数据,就是人家产品都没做好你就来提货,这显示是不行的

现在 callback 在定时器的 function 里执行,并且是在 data 变量初始化后才执行,就保证能拿到数据,即便定时器是10秒甚至一分钟都没关系,反正都是等 data 初始化后才执行 callback

还有种方式可以获取 data 的值,就是将其定义为全局变量,定时器一秒后执行,那就两秒后进行调用,但此方式没有意思

  1. var data
  2. function fn() {
  3. setTimeout(function () {
  4. data = 'Hi'
  5. },1000)
  6. }
  7. fn()
  8.  
  9. setTimeout(function () {
  10. console.log(data) //两秒后结果为Hi,若将2000改为0,结果为undefined
  11. },2000)

封装异步API

模拟 jq 的 ajax.get() 方法,封装原生 ajax

  1. var xhr = new XMLHttpRequest()
  2.   xhr.open('get', './db.json')
  3.   xhr.send()
  4.   xhr.onload = function () {
  5.   console.log(xhr.responseText)
  6. }

自定义 get() 方法,获取 ajax 响应数据

  1. function get(url,callback) {
  2.   var xhr = new XMLHttpRequest()
  3. xhr.open('get', url)
  4. xhr.send()
  5. xhr.onload = function () {
  6.   callback(xhr.responseText)
  7. }
    }
  8. get('./db.json',function (data) {
  9. console.log(data)
  10. })

还有个小栗子,Node 封装一个写入文件的小模块,在 app.js 中调用 writeFile.js 的方法,将数据写入 db.json 中

db.json 文件里有一个对象,里面是 json 数组,存储着两个学生的信息

writeFile.js

  1. var fs = require('fs')
  2.  
  3. exports.add = function (stuObj,callback) {
  4. //如果直接写入则会覆盖db.json原有内容,要先读取出来
  5. fs.readFile('./db.json','utf-8',function (err,data) {
  6. if(err){
  7. return callback(err) //读取失败,return为了结束readFile
  8. }
  9.  
  10. //文件中数据不是对象,所以只能先转为对象,再可以添加
  11. var arr = JSON.parse(data).Student
  12. stuObj.id = arr[arr.length - 1].id + 1 //设置id
  13. arr.push(stuObj)
  14.  
  15. //把对象转为字符串才能写入到db.json
  16. var fileData = JSON.stringify({Student:arr})
  17.  
  18. fs.writeFile('./db.json',fileData,function (err) {
  19. if(err){
  20. return callback(err)
  21. }
  22. callback(null) //写入成功,不需要返回err对象
  23. })
  24. })
  25. }

app.js

  1. //引包,得到writeFile.js导出的对象,此对象有个add属性,其值为一个方法
  2. var exportsObj = require('./writeFile')
  3.  
  4. //将data写入到db.json.数据应该由表单提交而来,但这里只是为了熟悉封装思路
  5. var data = {"name":"Aaron","sex":1}
  6.  
  7. //文件的读写的异步,所以需要回调函数来获取数据
  8. exportsObj.add(data,function (err) {
  9. if(err){
  10. console.log(err)
    }
  11. })

写入成功

有点蒙圈的时候可以想,回调函数是用来存储数据的,存储的数据在哪里被使用了,可能有助于回想整个过程

获取异步API数据的更多相关文章

  1. 解决GJson 获取web api数据出现Not a JsonObject问题

    服务器端web api服务采用asp.net web api编写,对请求的数据序列化成Json格式的字符串进行传递. 客户端采用Java进行接收处理,处理采用GJson进行解析,出现Not a Jso ...

  2. 通过Jquery异步获取股票实时数据

    最近朋友让我帮他做个异步获取数据的程序,暂时服务器什么都没有,所以我就想先拿股票数据打个框架,方便后续开发和移植等事情 代码如下: <!-- 说明:股票看盘 作者:黑桃A 时间:2014-04- ...

  3. 传递多个参数并获取Web API的数据

    近段时间学习Web Api觉得非常有意思.默认的路由情况之下,获取数据时,它不必指定Action操作名. 还有另外感想,就是自从学习asp.net MVC之后,加上jQuery,让Insus.NET已 ...

  4. react生命周期获取异步数据

    当react组件需要获取异步数据的时候,建议在ComponentDidMount周期里执行获取动作, 如果非异步数据,可以在ComponentWillMount获取 因为ComponentWillMo ...

  5. 【vue】获取异步加载后的数据

    异步请求的数据,对它做一些处理,需要怎么做呢?? axios 异步请求数据,得到返回的数据, 赋值给变量 info .如果要对 info 的数据做一些处理后再赋值给 hobby ,直接在 axios ...

  6. Code First系列之视图,存储过程和异步API

    返回<8天掌握EF的Code First开发>总目录 本篇目录 视图View 存储过程 使用存储过程CRUD 异步API 本章小结 自我测试 本系列的源码本人已托管于coding上:点击查 ...

  7. 使用腾讯开发平台获取QQ用户数据资料

    <今天是七夕:祝大家七夕嗨皮,前可么么哒,后可啪啪啪> Tips:本篇博客将教你如何使用腾讯开发平台获取QQ用户资料 ----------------------------------- ...

  8. 8天掌握EF的Code First开发系列之5 视图、存储过程和异步API

    本文出自8天掌握EF的Code First开发系列,经过自己的实践整理出来. 本篇目录 视图View 存储过程 异步API 本章小结 咱们接着上一篇继续深入学习,这一篇说说Entity Framewo ...

  9. 串行通讯之.NET SerialPort异步写数据

    目录 第1章说明    2 1 为什么需要异步写数据?    2 2 异步写数据的代码    2 3 源代码    4 第1章说明 1 为什么需要异步写数据? 如下图所示,以波特率300打开一个串口. ...

随机推荐

  1. ZooKeeper集群详细安装教程

    1. 安装JDK 1.1 官网下载JDK 进入网址<a href="http://www.oracle.com/technetwork/java/javase/downloads/jd ...

  2. HDU4560 二分最大流

    http://acm.hdu.edu.cn/showproblem.php?pid=4560 网络流好像经常搭配上二分和拆点. n个歌手,m种歌曲流派(n<=m<=75) 我们想要安排尽可 ...

  3. Django REST Framework extensions

    GitHub:https://github.com/chibisov/drf-extensions 官方文档:http://chibisov.github.io/drf-extensions/docs ...

  4. git ssh https 踩坑记 ---- 域账号密码更新

    前几天突然通知要更新公司的域账号密码,然后git pull就一直报 fatal: Authentication failed for 'https://git ... 很奇怪的是,有一个项目git p ...

  5. TF的使用

      激活函数 关于激活函数的介绍请参考:激活函数 这里只是记录TF提供的激活函数 import tensorflow as tf a = tf.nn.relu( tf.matmul(x, w1) + ...

  6. GlusterFS 分布式文件系统的使用入门-管理GlusterFS卷

    GlusterFS 分布式文件系统的使用入门-管理GlusterFS卷 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.卷的扩容 您可以根据需要在群集联机且可用时扩展卷.例如,您 ...

  7. Linux环境变量总结

    现在每天测试到时候会与Linux打交道,自然也会用到环境变量了.看了网上几篇文章,结合自己到实践和看法,总结以下Linux的环境变量吧.一.什么是环境变量?环境变量相当于给系统或用户应用程序设置的一些 ...

  8. 用itext合并多个pdf文件【转】【补】

    java代码 package c; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arra ...

  9. 那些年我们没能bypass的xss filter[from wooyun]

    原文链接:http://zone.wooyun.org/content/6899 小弟初学xss才10天.不过个人很喜欢收集xss payload.在这里把自己平时挖xss时会用到的payloads列 ...

  10. Github 开源项目(二)gorun (go语言工具)

    gorun是一个工具,可以在Go程序的源代码中放置“爆炸线”来运行它,或者明确运行这样的源代码文件. 它的创建旨在试图让Go更加吸引那些习惯于Python和类似语言的人们,他们使用源代码进行最明显的操 ...