vue 回调函数(callback)的用法

news2024/11/24 19:43:44

一、介绍:

1、前提:在 js 中,函数也是对象,可以赋值给变量,可以作为参数放在函数的参数列表中,如:

var doSomething = function(a,b){
 return a + b;
}
console.log(doSomething(2,3));

2、概念:
callback 是一种特殊的函数,这个函数被作为参数传给另一个函数去调用,这样的函数就是回调函数。回调,顾名思义,回头再调。回调与同步、异步并没有直接的联系,回调只是一种实现方式,既可以有同步回调,也可以有异步回调,还可以有事件处理回调和延迟函数回调。

3、语法:
在大多数编程语言中,函数的形参总是从外向内传递参数,但在JS中,如果形参碰到“关键字” callback 则完全相反,它表示从内向外反向调用某个外部函数。

二、举例

1、举例介绍:

(1)第一步:

var fs = require("fs");
var c

function f(param) {
    console.log(param)
}
 
function writeFile() {
    fs.writeFile('input.txt', 'fs.writeFile 写入文件的内容', function (err) {
        if (!err) {
            console.log("文件写入完成")
            c = 1
        }
    });
}
 
c = 0
writeFile()
f(c)

打印结果为0,因为程序运行到writeFile()这一行的时候,是一个比较耗时的IO操作,JS碰到这种操作并不会停在原地一直等待直到函数执行完毕,而是直接运行下一条代码(即f©),而此时 c = 1这一行代码其实并没有被执行到,所以打印出来的结果还是0 !,如果希望打印1,可以使用第二步的代码:

(2)第二步:

var fs = require("fs");
var c
 
function f(param) {
    console.log(param)
}
 
function writeFile() { 
    fs.writeFile('input.txt', 'fs.writeFile 写入文件的内容', function (err) {
        if (!err) {
            console.log("文件写入完成")
            c = 1
            f(c)
        }
    });
}
 
c = 0
writeFile() 

这样结果是对的,但是改成这样并不完美,因为这么做就相当于将f()写死在writeFile()里了,如果此处我想根据不同的场景调用不同的函数还要写几个不同的writeFile(),而他们之间的区别仅仅是最后调用的那个函数不同,这里就体现callback的作用了(准确地说callback并不真的是Javascript里的关键字,只是大家都约定成俗把callback这个单词作为回调函数的默认选择)。看下使用回调函数后的代码:

(3)第三步:回调函数写法

var fs = require("fs");
 
function f(param) {
    console.log(param)
}
 
function writeFile(callback) { //callback,表示这个参数不是一个普通变量,而是一个函数
    fs.writeFile('input.txt', 'fs.writeFile 写入文件的内容', function (err) {
        if (!err) {
            console.log("文件写入完成")
            c = 1
            callback(c) // 因为我们传进来的函数名是f(),所以此行相当于调用一次f(c)
        }
    });
}
var c = 0
writeFile(f) // 函数f作为一个参数传进writeFile函数

经过改造后的代码出现了两次callback,第一个callback出现在writeFile的形参里,起定义的作用,表示这个参数并不是一个普通变量,而是一个函数,即所谓的“以函数为参数”。 第二个callback出现在c = 1下面,表示此处“执行”从形参传递进来的那个函数。这样一来,writeFile()函数在执行完毕之后到底调用哪个函数就变“活”了,如果我们想writeFile()函数执行完之后并不是像第二个例子那样只能调用f(),而是还有别的函数比如说x() y() z(),那么只需要写成 writeFile(x),writeFile(y)… 就行了。PS: 此处并不一定非要写为“callback”,你可以任意写成a,b,c…callback只是一种约定俗成的写法,它明确地告诉代码阅读者:此处是一个回调函数。

但是这步写法不够简洁,一些函数的形参列表里直接嵌套一个函数的情况,其本质上仍然是回调函数,因为没有了函数名,所以也称匿名函数。看下最终的简化写法:

(4)第四步:匿名回调函数

var fs = require("fs");
 
function writeFile(callback) { 
    fs.writeFile('input.txt', '我是通过fs.writeFile 写入文件的内容', function (err) {
        if (!err) {
            console.log("文件写入完毕!")
            c = 1
            callback(c) 
        }
    });
}
var c = 0
writeFile(function (param) {
    console.log(param)
})

这是最简洁的写法,再举几个例子:

var doit = function(callback)
{
    var a = 1,
        b = 2,
        c = 3;
    var t = callback(a,b,c);
    return t + 10;
};
var d = doit(function(x,y,z){
    return (x+y+z);
});
console.log(d);

export default {
  created() {
    this.testCallBack();
  },
  methods: {
    testCallBack() {
      let param = '测试'
      this.myCallback(param, function (arg1, arg2) {
        alert('这是回调' + arg1 + ' ' + arg2)
      });
    },
    myCallback(param, callback) {
      setTimeout(() => {
        alert(param)
        callback(param, '222');
      }, 1000);
    }
  }
}

readImageFile(origin, quality, file) {
      let that = this;
      let fileName = file.name;
      let reader = new FileReader();
      reader.onload = function(evt) {
        let base64File = evt.target.result;
        that.imageCompress(
          base64File,
          origin,
          {
            quality
          },
          function(result) {
            let blobFile = that.dataURLtoBlob(result);
            let compressFile = new window.File([blobFile], fileName, { type: file.type });
            that.uploadFile(compressFile);
          }
        );
      };
      reader.readAsDataURL(file);
    },
    // 压缩图片
    imageCompress(path, Orientation, obj, callback) {
      let img = new Image();
      img.src = path;
      img.onload = function() {
        let that = this;
        // 默认按比例压缩
        let imgWidth = that.width;
        let imgHeight = that.height;
        let scale = imgWidth / imgHeight;
        if (imgWidth > MAX_IMAGE_WIDTH) {
          imgWidth = MAX_IMAGE_WIDTH;
          imgHeight = imgWidth / scale;
        }
        let quality = obj.quality || 0.7; // 默认图片质量为0.7
        // 生成canvas
        let canvas = document.createElement('canvas');
        let ctx = canvas.getContext('2d');
        let anw = document.createAttribute('width');
        let anh = document.createAttribute('height');

        anw.nodeValue = imgWidth;
        anh.nodeValue = imgHeight;
        canvas.setAttributeNode(anw);
        canvas.setAttributeNode(anh);
        ctx.drawImage(that, 0, 0, imgWidth, imgHeight);
        // quality值越小,所绘制出的图像越模糊
        let base64 = canvas.toDataURL('image/jpeg', quality);
        // 回调函数返回base64的值
        callback(base64);
      };
    },

function doSomething(msg, callback){
    alert(msg);
    if(typeof callback == "function") 
    callback();
 } 
doSomething("回调函数", function(){
    alert("匿名函数实现回调!");
 }); 

2、常见的回调函数例子:
在这里插入图片描述
三、回调函数中this的指向:
callback中的this指向window。可以使用Call和Apply函数来改变this指向,每个Javascript中的函数都有两个方法:Call 和 Apply。这些方法被用来设置函数内部的this对象以及给此函数传递变量。

举例:

var clientData = {
    id: 096545,
    fullName: "Not Set",
    //setUsrName是一个在clientData对象中的方法
    setUserName: function (firstName, lastName){
        this.fullName = firstName + " " + lastName;
    }
} 

function getUserInput(firstName, lastName, callback){
    //code .....

    //调用回调函数存储
    callback(firstName, lastName);
}

getUserInput("Barack","Obama",clientData.setUserName);

console.log(clientData.fullName);  //Not Set

console.log(window.fullName);  //Barack Obama

在上面的代码中,当clientData.setUsername被执行时,this.fullName并没有设置clientData对象中的fullName属性,它将设置window对象中的fullName属性。

下面我们看下Apply函数实现,Call函数类似。(call接收的第一个参数为被用来在函数内部当做this的对象,传递给函数的参数被挨个传递。Apply函数的第一个参数也是在函数内部作为this的对象,然而最后一个参数确是传递给函数的值的数组。)

//注意到我们增加了新的参数作为回调对象,叫做“callbackObj”
function getUserInput(firstName, lastName, callback ,callbackObj){
         //code .....

        callback.apply(callbackObj, [firstName, lastName]);
}

getUserInput("Barack", "Obama", clientData.setUserName, clientData);

console.log(clientData.fullName); //Barack Obama

四、回调函数的使用场景:

1、回调函数经常使用于以下场景:

异步调用(例如读取文件,进行HTTP请求,动态加载js文件,加载iframe资源后,图片加载完成执行回调等等)
事件监听器/处理器
setTimeout和setInterval方法
一般情况:精简代码

2、以异步调用为例,回调函数与异步编程:回调函数是实现异步编程的利器,在程序运行中,当某些请求过程漫长,我们有时没必要选择等待请求完成继续处理下一个任务,这时使用回调函数进行异步处理可以大大提高程序执行效率。例如:AJAX请求。若是使用回调函数进行处理,代码就可以继续进行其他任务,而无需空等。实际开发中,经常在javascript中使用异步调用!下面有个使用AJAX加载XML文件的示例,并且使用了call()函数,在请求对象(requested object)上下文中调用回调函数。

function fn(url, callback){
 var httpRequest;    //创建XHR
 httpRequest = window.XMLHttpRequest ? new XMLHttpRequest() :   //针对IE进行功能性检测
    window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : undefined;
  
 httpRequest.onreadystatechange = function(){
  if(httpRequest.readystate === 4 && httpRequest.status === 200){  //状态判断
   callback.call(httpRequest.responseXML); 
  }
 };
 httpRequest.open("GET", url);
 httpRequest.send();
}
 
fn("text.xml", function(){    //调用函数
 console.log(this);                 / /此语句后输出
});
 
console.log("this will run before the above callback.");  //此语句先输出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/336970.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

神经网络基础部件-BN层详解

一,数学基础 1.1,概率密度函数 随机变量(random variable)是可以随机地取不同值的变量。随机变量可以是离散的或者连续的。简单起见,本文用大写字母 XXX 表示随机变量,小写字母 xxx 表示随机变量能够取到…

Zabbix 构建监控告警平台(二)--

Apache监控示例(图形监控)模板TemplateZabbix Items 1.Apache监控示例(图形监控) 1.1创建主机组 在“配置”->“主机群组”->“创建主机群组” 填入组名“webserver_test” 创建完成之后可以在“配置”->"主机群组&…

界面控件DevExpress WinForm中文教程 - 如何使用模板库构建类Office UI?

DevExpress WinForm拥有180组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForm能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任…

opengl glsl shader vscode安装插件glsl_canvas 和 shader languagesupportForVS Code

u_resolution 是画布尺寸,即代表画布宽高 //给内置变量gl_PointSize赋值像素大小,注意值是浮点数 gl_PointSize20.0; // 片元沿着x方向渐变 gl_FragColor vec4(gl_FragCoord.x/500.0*1.0,1.0,0.0,1.0); // 接收插值后的纹理坐标 varying vec2 v…

作为开发人员您会喜欢的 7 个免费公共 API

1. JSON 占位符JSON Placeholder是一项服务,可为您提供用于测试和原型制作的假在线REST API 。这是每个开发人员的首选 API。2.谷歌翻译Google有大量的API,但其中大部分是付费的。值得庆幸的是,Translate API提供100 多种语言的免费翻译&…

Spring面试重点(二)——Spring循环依赖

Spring循环依赖 什么是循环依赖? 从字面上来理解就是A依赖B的同时B也依赖了A,就像上面这样,或者C依赖与自己本身。体现到代码层次就是这个样子 Component public class A { // A中注入了B Autowired private B b; }---Component public cla…

@Valid注解配合属性校验注解完成参数校验并且优化异常处理

Valid注解配合属性校验注解完成参数校验并且优化参数校验异常处理1 Valid注解配合属性校验注解完成参数校验2 优化参数校验异常处理1 Valid注解配合属性校验注解完成参数校验 向数据库商品分类表中新增商品分类字段,并校验传入的参数 不使用注解的传统方法&#xf…

基于python+django社区报修维修平台

本系统主要分为前后和后台页面,前台页面主要功能有:首页,座位信息,交流论坛,公告信息,个人中心,后台管理。后台页面分为:首页,个人中心,学生管理,教师管理,座位信息管理,座位预约管理,班级信息管理,签到信息管理,离开信息管理,座位暂离管理,举报信息管理…

MLX90614红外温度计介绍

MLX90614红外温度计简介MLX90614是一款红外非接触温度计。TO-39金属封装里同时集成了红外感应热电堆探测器芯片和信号处理专用集成芯片。由于集成了低噪声放大器、17位模数转换器和强大的数字信号处理单元,使得高精度和高分辨度的温度计得以实现。温度计具备出厂校准…

如何上传文件

在页面上面&#xff0c;form 表单里面添加属性enctype"multipart/form-data" 比如&#xff1a; <form name"frm" method"post" enctype"multipart/form-data"> 添加文件选择框&#xff1a; <input type"file" na…

安全上下文

目录 文章目录目录本节实战前言1、为 Pod 设置 Security Context2、为容器设置 Security Context3、设置 Linux Capabilities1.Linux Capabilities&#xff08;1&#xff09;什么是 Capabilitie&#xff08;2&#xff09;Capabilities 的赋予和继承&#xff08;3&#xff09;如…

ctfshow 年ctf

文章目录除夕初一初二初三初四初五初六官方wp除夕 include "flag.php";$year $_GET[year];if($year2022 && $year1!2023){echo $flag; }else{highlight_file(__FILE__); }弱比较和强比较的问题 2023那里是强比较&#xff0c;还是很容易的 /?year2022.0科…

CHI协议定义的NOC组件

请求结点RN 可以向NOC发送读/写等请求事务&#xff0c;有以下几种类型的RN&#xff1a; RN-F 一般是处理器核或者核簇结点&#xff0c;包含了局部cache和一致性部件snoopee。与NOC上的一致性部件一起&#xff0c;维护“可缓存”数据的一致性&#xff08;这种可缓存数据…

实验名称:基于C/S的命名管道通信

实验名称&#xff1a;基于C/S的命名管道通信 相关知识 无名管道 无名管道&#xff08;匿名管道&#xff09;用于具有亲缘关系进程间的通信&#xff0c;其特点有 管道是半双工的&#xff0c;数据单向流动&#xff08;双方通信需建立两个通道&#xff09;管道只能用于父子进程…

2023年房地产投资-租金和IRR研究报告

第一章 概况 房地产投资租赁是指置业投资者在购买到物业后&#xff0c;首先对该物业进行适当整饰与装修&#xff0c;之后以出租人的身份&#xff0c;以口头协议或签订合同的形式&#xff0c;将房屋交付承租人占有、使用与收益&#xff0c;由承租人向出租人交付租金的行为。通过…

第一章 企业管理概论

目录 一、企业及其形式 二、企业管理概述 三、企业管理理论与实践的产生与发展 四、网络时代的企业环境 五、网络时代企业管理的变革 一、企业及其形式 1、企业的概念 企业以市场为导向&#xff0c;以价值增值作为经济活动的目的&#xff1b; 企业是从事商品生产和流通的…

BUG解决:微信小程序调用vantweapp遮罩层popup 更改show后没反应,弹框/遮罩层不隐藏,show失效

一、bug复现&#xff1a;引入popup组件&#xff0c;时间选择组件json>"usingComponents": {"van-datetime-picker": "vant/weapp/datetime-picker/index","van-popup": "vant/weapp/popup/index"}页面想实现&#xff0c;…

当我以为z-library已死的时候 它居然又活了?!!

z-library 全世界最大的图书馆What Happened To Z-lib?zlib的复活只是暂时的deepweb会让zlib得到永生&#xff01;真心祝愿zlib的Plans for 2023能够实现What Happened To Z-lib? 这是曾经的zlib&#xff0c;域名是z-lib.org&#xff0c;然而现在死了&#xff08;22年11月时…

Grafana 系列文章(十三):如何用 Loki 收集查看 Kubernetes Events

前情提要 IoT 边缘集群基于 Kubernetes Events 的告警通知实现IoT 边缘集群基于 Kubernetes Events 的告警通知实现&#xff08;二&#xff09;&#xff1a;进一步配置 概述 在分析 K8S 集群问题时&#xff0c;Kubernetes Events 是超级有用的。 Kubernetes Events 可以被当…

Windows 10 Creators版本中的11个大亮点

导读微软在近日公布了有关明年Windows 10更新部分的大量功能&#xff0c;但该公司在其Creators更新版本中悄悄隐藏了远超出11项新的功能。其实&#xff0c;在这个更新包中还将包含许多内容&#xff0c;包括增加一个新的应用程序&#xff0c;以及针对Edge浏览器、地图应用程序和…