异步编程

await

在JavaScript中,await关键字用于等待一个异步操作完成,并返回异步操作的结果。当遇到await关键字时,JavaScript引擎会暂停当前函数的执行,直到异步操作完成并返回结果。在等待异步操作的过程中,JavaScript引擎会继续执行其他代码。

因此,await关键字的执行顺序是从上到下的,即在遇到await关键字之前的代码会先执行,然后等待异步操作完成后,再执行await关键字之后的代码。如果在await关键字之前的代码中抛出了异常,那么await关键字之后的代码将不会执行。

在你提供的代码片段中,当遇到await关键字时,JavaScript引擎会等待addCoCertificationupdateCoCertification函数完成,并返回它们的结果。在等待这些函数的过程中,JavaScript引擎会继续执行其他代码,例如设置isAddedFile.valuedialogVisible.value的值。当异步操作完成后,JavaScript引擎会继续执行await关键字之后的代码,例如显示成功消息。

总之,await关键字的执行顺序是从上到下的,即在遇到await关键字之前的代码会先执行,然后等待异步操作完成后,再执行await关键字之后的代码。

下面是一个简单的示例,演示了await关键字的执行顺序:

1function sleep(ms) {2  return new Promise(resolve => setTimeout(resolve, ms))3}45async function example() {6  console.log('Start')78  await sleep(1000)9  console.log('After 1 second')1011  await sleep(2000)12  console.log('After 2 more seconds')1314  console.log('End')15}1617example()

在这个示例中,我们定义了一个sleep函数,它返回一个Promise对象,并在指定的时间后将其状态设置为resolved。然后,我们定义了一个名为example的异步函数,它使用await关键字等待sleep函数完成,并在控制台中打印一些消息。在example函数中,我们使用await关键字等待sleep(1000)函数完成,并在1秒后打印"After 1 second"。然后,我们再次使用await关键字等待sleep(2000)函数完成,并在2秒后打印"After 2 more seconds"。最后,我们在控制台中打印"End"。

当我们调用example函数时,JavaScript引擎会执行console.log('Start')语句,然后等待sleep(1000)函数完成。在等待的过程中,JavaScript引擎会继续执行其他代码,但是当sleep(1000)函数完成后,JavaScript引擎会继续执行await关键字之后的代码,即打印"After 1 second"。然后,JavaScript引擎会等待sleep(2000)函数完成,并在2秒后打印"After 2 more seconds"。最后,JavaScript引擎会打印"End"。


在同步方法中使用await关键字是不合法的,因为await只能在异步函数中使用。如果你在同步函数中使用await关键字,它会被视为普通的表达式,不会暂停当前函数的执行。

如果你需要在同步函数中等待一个异步操作完成,你可以使用Promise对象和then方法来实现。例如,你可以将异步操作封装在一个Promise对象中,并在then方法中处理结果。下面是一个示例:

1function sleep(ms) {2  return new Promise(resolve => setTimeout(resolve, ms))3}45function example() {6  console.log('Start')78  sleep(1000).then(() => {9    console.log('After 1 second')10    return sleep(2000)11  }).then(() => {12    console.log('After 2 more seconds')13    console.log('End')14  })15}1617example()

在这个示例中,我们定义了一个sleep函数,它返回一个Promise对象,并在指定的时间后将其状态设置为resolved。然后,我们定义了一个名为example的同步函数,它使用Promise对象和then方法等待sleep函数完成,并在控制台中打印一些消息。在example函数中,我们使用sleep(1000).then()方法等待sleep(1000)函数完成,并在1秒后打印"After 1 second"。然后,我们再次使用then方法等待sleep(2000)函数完成,并在2秒后打印"After 2 more seconds"和"End"。

当我们调用example函数时,JavaScript引擎会执行console.log('Start')语句,然后等待sleep(1000)函数完成。在等待的过程中,JavaScript引擎会继续执行其他代码,但是当sleep(1000)函数完成后,JavaScript引擎会执行then方法中的代码,即打印"After 1 second"。然后,JavaScript引擎会等待sleep(2000)函数完成,并在2秒后打印"After 2 more seconds"和"End"。

数组

map

map方法会对数组中的每个元素都执行一个回调函数,并返回一个新的数组,新数组中的元素是回调函数的返回值。map方法不会改变原始数组,而是返回一个新的数组。下面是一个使用map方法的示例:

1const numbers = [1, 2, 3, 4, 5];2const doubledNumbers = numbers.map((number) => number * 2);3console.log(doubledNumbers); // [2, 4, 6, 8, 10]

在这个示例中,我们使用map方法将数组中的每个元素都乘以2,并返回一个新的数组doubledNumbers

filter

filter方法会对数组中的每个元素都执行一个回调函数,并返回一个新的数组,新数组中的元素是回调函数返回true的元素。filter方法不会改变原始数组,而是返回一个新的数组。下面是一个使用filter方法的示例:

1const numbers = [1, 2, 3, 4, 5];2const evenNumbers = numbers.filter((number) => number % 2 === 0);3console.log(evenNumbers); // [2, 4]

在这个示例中,我们使用filter方法筛选出数组中的偶数,并返回一个新的数组evenNumbers

总之,mapfilter都是JavaScript中常用的数组方法,它们可以用于对数组进行转换和筛选。map方法会对数组中的每个元素都执行一个回调函数,并返回一个新的数组,新数组中的元素是回调函数的返回值。filter方法会对数组中的每个元素都执行一个回调函数,并返回一个新的数组,新数组中的元素是回调函数返回true的元素。

reduce

reduce() 函数是 JavaScript 中的一个高阶函数,它可以将一个数组中的所有元素通过一个函数进行累加,最终返回一个累加结果。reduce() 函数接收两个参数:一个回调函数和一个初始值。回调函数接收四个参数:累加器当前元素当前索引原始数组。在每次迭代中,回调函数都会将累加器和当前元素作为参数,并返回一个新的累加器值。最终,reduce() 函数返回最后一次调用回调函数时的累加器值。

1const numbers = [65, 44, 12, 4]2// total为 累加器 item为当前元素3// 0 为初始值,也就是 从什么值开始累加4const totalNumber = () => {5    return numbers.reduce((total, item) => {6        return total + item7    }, 0)8}

循环

for...in

for...in语句用于遍历对象的可枚举属性,包括对象自身的属性和继承的属性。在遍历时,for...in会将属性名作为变量传递给循环体,因此我们可以通过属性名来访问属性的值。下面是一个使用for...in语句遍历对象的示例:

1const obj = { a: 1, b: 2, c: 3 };2for (const key in obj) {3  console.log(key, obj[key]);4}5// Output:6// a 17// b 28// c 3

在这个示例中,我们使用for...in语句遍历对象obj的属性,并将属性名作为变量key传递给循环体。在循环体中,我们可以通过obj[key]来访问属性的值。

for...of

for...of语句用于遍历可迭代对象,包括数组、字符串、Map、Set等。在遍历时,for...of会将元素的值作为变量传递给循环体,因此我们可以直接访问元素的值。下面是一个使用for...of语句遍历数组的示例:

1const arr = [1, 2, 3];2for (const item of arr) {3  console.log(item);4}5// Output:6// 17// 28// 3

在这个示例中,我们使用for...of语句遍历数组arr的元素,并将元素的值作为变量item传递给循环体。在循环体中,我们可以直接访问元素的值。

总之,for...infor...of都是JavaScript中用于遍历数据结构的循环语句,但它们的作用和用法有所不同。for...in语句用于遍历对象的可枚举属性,而for...of语句用于遍历可迭代对象的元素。

下载文件

Url转Blob

1// xhr2function urlToBlob(url, callback) {3  var xhr = new XMLHttpRequest();4  xhr.open('GET', url, true);5  xhr.responseType = 'blob';67  xhr.onload = function() {8    if (xhr.status === 200) {9      var blob = xhr.response;10      callback(null, blob);11    } else {12      callback(new Error('Unable to fetch blob'));13    }14  };1516  xhr.onerror = function() {17    callback(new Error('Network error'));18  };1920  xhr.send();21}22// fetch23function urlToBlob(url) {24  return fetch(url)25    .then(response => {26      if (!response.ok) {27        throw new Error('Unable to fetch blob');28      }29      return response.blob();30    });31}

匿名函数和箭头函数

区别

匿名函数和箭头函数都是JavaScript中的函数形式,它们之间有一些重要的区别。

  1. 语法结构:匿名函数使用function关键字来定义,后面跟随函数名称(可选),参数列表和函数体。例如:
1var anonymousFunc = function(arg1, arg2) {2  // 函数体3};

而箭头函数使用箭头操作符(=>)来定义,后面跟随参数列表和箭头函数体。没有显式的函数名称。例如:

1var arrowFunc = (arg1, arg2) => {2  // 函数体3};
  1. this 的指向:在匿名函数中,this 的指向是动态的,根据函数的调用方式而定。而在箭头函数中,this 的指向是词法作用域的,它继承自外围作用域。箭头函数没有自己的 this 值,它会使用外围作用域的 this 值。这使得箭头函数在处理函数上下文时更加方便。
  2. arguments 对象:匿名函数中可以使用 arguments 对象访问函数的参数列表。而箭头函数没有自己的 arguments 对象,它会继承外围作用域中的 arguments 对象。
  3. 构造函数:匿名函数可以用作构造函数来创建新对象。而箭头函数没有原型对象,因此不能用作构造函数,尝试使用 new 关键字调用箭头函数会抛出错误。
  4. 箭头函数的简洁语法:箭头函数提供了更简洁的语法,尤其是在处理简单的函数体时。当函数体只有一条表达式时,可以省略花括号和 return 关键字,并将表达式的结果隐式返回。

这些是匿名函数和箭头函数之间的一些主要区别。选择使用哪种函数形式取决于具体的使用场景和需求。匿名函数适用于更传统的函数定义和需要动态 this 指向的情况,而箭头函数则提供了更简洁的语法和更方便的函数上下文处理。

运算符

~

在 JavaScript 中,~ 符号是按位取反运算符。它将操作数的每个二进制位取反,即将 0 变为 1,将 1 变为 0。然后返回这个值的负数加一。

例如,对于十进制数 10,它的二进制表示为 1010,按位取反后变为 0101,即 5。因此,~10 的结果为 -11。

性能优化

防抖(debounce)

多次触发 只执行最后一次

作用:高频率触发的事件,在指定的单位时间内,只相应最后一次,如果在指定时间内再次触发,则重新计算时间。

防抖类似于英雄联盟回城6秒,如果回城中被打断,再次回城需要再等6秒

JavaScript常用知识整理_数组

实现代码:

1<body>2    <input type="text" id="inp">3    <script>4    5        // 1.封装防抖函数6        function debounce(fn, time) {7            // 4.创建一个标记用来存放定时器的返回值8            let timeout = null;9            return function () {10                // 5.每当用户触发input事件  把前一个 setTimeout 清楚掉11                clearTimeout(timeout);12                // 6.然后又创建一个新的 setTimeout, 这样就能保证输入字符后等待的间隔内 还有字符输入的话,就不会执行 setTimeout里面的内容13                timeout = setTimeout(() => {14                    // 7.这里进行防抖的内容15                    fn();16                }, time);17            };18        }1920        // 2.获取inpt元素21        var inp = document.getElementById('inp');22        // 8. 测试防抖临时使用的函数23        function sayHi() {24            console.log('防抖成功');25        }26        // 3.给inp绑定input事件  调用封装的防抖函数  传入要执行的内容与间隔事件 27        inp.addEventListener('input', debounce(sayHi, 5000)); 2829    </script>30</body>

使用场景:

search搜索时,用户在不断输入值时,用防抖来节约请求资源。

节流(throttle)

规定时间内 只触发一次

作用:高频率触发的事件,在指定的单位时间内,只响应第一次

节流类似于英雄联盟里的技能 触发一次必须等技能刷新后才能再次触发

JavaScript常用知识整理_回调函数_02

实现代码:

1<script>2    // 1.封装节流函数3    function throttle(fn, time) {4        //3. 通过闭包保存一个 "节流阀" 默认为false5        let temp = false;6        return function () {7            //8.触发事件被调用 判断"节流阀" 是否为true  如果为true就直接trurn出去不做任何操作8            if (temp) {9                return;10            } else {11                //4. 如果节流阀为false  立即将节流阀设置为true12                temp = true; //节流阀设置为true13                //5.  开启定时器14                setTimeout(() => {15                    //6. 将外部传入的函数的执行放在setTimeout中16                    fn.apply(this, arguments);17                    //7. 最后在setTimeout执行完毕后再把标记'节流阀'为false(关键)  表示可以执行下一次循环了。当定时器没有执行的时候标记永远是true,在开头被return掉18                    temp = false;19                }, time);20            }21        };22    }23    function sayHi(e) {24        // 打印当前 document 的宽高25        console.log(e.target.innerWidth, e.target.innerHeight);26    }27    // 2.绑定事件,绑定时就调用节流函数  28    // 敲黑板!!! 这里是重点 绑定是就要调用一下封装的节流函数 触发事件是触发封装函数内部的函数29    window.addEventListener('resize', throttle(sayHi, 2000));30</script>

使用场景:

鼠标不断点击触发,mousedown(单位时间内只触发一次)

监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断