zoukankan      html  css  js  c++  java
  • 获取异步API数据

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

    js 中的异步操作:

    ❶ 定时器

    ❷ 事件绑定

    ❸ ajax异步模式

    ❹ 回调函数

     

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

    function fn() {
      setTimeout(function () {
          var data = 'Hi'
       },1000)
      console.log(data) } fn()

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

     

    function fn() {
        setTimeout(function () {
            var data = 'Hi'
            return data
        },1000)
    }
    console.log(fn())

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

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

     

    var data = '^_^'
    function fn() {
        setTimeout(function () {
            data = 'Hi'
        },1000)
        return data
    }
    console.log(fn())

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

     

    正确方式

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

    function fn(callback) {
        //传入一个函数,就相当于在这创建了一个叫callback的函数
        //var callback = function (data) { console.log(data) }
        setTimeout(function () {
            var data = 'Hi'
            callback(data)
        },1000)
    }
    fn(function (data) {
        console.log(data)
    })

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

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

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

    var data
    function fn() {
        setTimeout(function () {
            data = 'Hi'
        },1000)
    }
    fn()
    
    setTimeout(function () {
        console.log(data)  //两秒后结果为Hi,若将2000改为0,结果为undefined
    },2000)

    封装异步API

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

    var xhr = new XMLHttpRequest()
      xhr.open('get', './db.json')
      xhr.send()
      xhr.onload = function () {
      console.log(xhr.responseText)
    }

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

    function get(url,callback) {
      var xhr = new XMLHttpRequest()
       xhr.open('get', url)
       xhr.send()
       xhr.onload = function () {
         callback(xhr.responseText)
       }
    } get(
    './db.json',function (data) { console.log(data) })

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

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

     

    writeFile.js

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

     

    app.js

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

    写入成功 

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

  • 相关阅读:
    经典面试题之——如何自由转换两个没有继承关系的字段及类型相同的实体模型,AutoMapper?
    MySQL高效分页-mybatis插件PageHelper改进
    bat/cmd批处理程序设计教程
    除法与模运算的识别-大量除法推导过程
    进程 线程 协程的相关理解
    音素音标
    如何免费的让网站启用HTTPS
    破解笔记
    Linux的.a、.so和.o文件 对比 window下的dll,lib,exe文件
    注册表启动的位置
  • 原文地址:https://www.cnblogs.com/Grani/p/9588221.html
Copyright © 2011-2022 走看看