博客列表 >异步编程原理与示例演示/模块成员导入导出

异步编程原理与示例演示/模块成员导入导出

吴长清
吴长清原创
2022年08月02日 16:52:55456浏览

1.xhr与fetch异步编程的步骤,实例演示

1.1 同步与异步/进程与线程

(一)同步与异步

  1. 同步: 顺序执行, 优点: 静态预判结果可控, 缺点: 耗时任务阻塞执行
  2. 异步: 乱序执行, 优点: 不会阻塞代码,体验好, 缺点: 顺序不可控

以银行排队办业务为例

  1. 同步: 默认排队叫号, 依次办理
  2. 异步: 耗时任务(如修改密码忘带shen份证)则离开队列, 后面任务继续
  3. 任务队列: 取了shen份证回来了, 就待在”任务队列”中等待再次叫号

哪些是异步任务(耗时)?

  1. 定时任务: setTimeout, setInterval
  2. 事件监听: addEventListener
  3. 网络请求: ajax, promise,fetch
  4. 文件读写等涉及IO的操作

(二) 进程与线程

  1. 进程: 程序的运行状态, 执行实例
  2. 一个cpu同一时刻只能执行一个进程,通过上下文切换实现多任务,除非多核
  3. 线程: 进程中的某个任务,即一个进程,可以由多个线程完成
  4. js的特征,决定了它只能是单线程,例如dom操作中, 增删元素就不可能同时进行
  5. 单线程可确保js按用户要求的顺序执行,并确定业务逻辑正确,结果可控
  6. 但是单线程,也决定了所有任务必须在一个执行栈中完成,导致耗时任务必然会阻塞整个线程
  7. 解决文案: 任务队列与事件循环(事件轮询)
    通信解释:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html

(三) 单线程,任务队列,事件循环之间的关系与协同

  1. js所有任务都在主线程中”同步”执行
  2. 异步任务以回调的形式声明,并离开主线程,交给多线程的浏览器去执行
  3. 异步任务执行完毕,进入到”任务队列”中排队等待进入主线程执行
  4. 主线程同步任务全部完成后, 通过”事件循环”查询”任务队列”中是否有等待的任务
  5. 如果有,则该就绪任务进入主线程同步执行
  6. 该任务完成后, 事件循环会再次取出下一个就绪的异步任务进入主线程
  7. 以上过程不断重复, 直到主线程中的同步任务, 任务队列中的异步任务全部执行完毕

此图异步执行原理有误,个人理解

1.2 传统异步 xhr

  1. 创建对象: new XMLHttpRequest();
  2. 响应类型: xhr.responseType = "json";
  3. 配置参数: xhr.open("GET", url, true);
  4. 请求回调: xhr.onload = () => console.log(xhr.response);
  5. 失败回调: xhr.onerror = () => console.log("Error");
  6. 发起请求: xhr.send(null);
    xhr 至少监听2个事件: load,error, 调用2个函数: open,send
    post请求,需要设置一下请求头与请求的数据,其它与get请求完全相同
  1. <button onclick="getUser1(this)">查询用户信息: XHR</button>
  2. <script>
  3. function getUser1(btn) {
  4. //1. 创建对象
  5. const xhr = new XMLHttpRequest();
  6. //2. 响应类型
  7. xhr.responseType = "json";
  8. //3. 配置参数
  9. // 不传get参数,默认返回全部用户, 用table显示
  10. let url = "http://website.io/users.php";
  11. // 如果有get参数,用户id,用ul列表显示
  12. // url = "http://website.io/users.php?id=1";
  13. xhr.open("GET", url);
  14. //4. 请求回调
  15. xhr.onload = () => {
  16. console.log(xhr.response);
  17. // 将数组渲染到页面中
  18. render(xhr.response, btn);
  19. };
  20. //5. 失败回调
  21. xhr.onerror = () => console.log("Error");
  22. //6. 发起请求
  23. xhr.send(null);
  24. }
  25. </script>
  26. <script src="../js/function.js"></script>

1.3 fetch异步编程

语法:fetch(url).them(getRes).them(handleRes).catch(err)
url 请求响应地址
getRes 回调函数 返回json response.json()
handleRes 回调函数 得到JSON并处理
err 处理异步执行的错误信息

fetch api 浏览器原生实现的异步技术
axios基于 xhr / fetch
fetch基于Promise, 返回 Promise对象

  1. window.addEventListener("load", ()=>{
  2. let url = "https://jsonplaceholder.typicode.com/users";
  3. fetch(url)
  4. .then((response) => response.json())
  5. .then((json) => {
  6. // 打印到控制台
  7. console.log(json);
  8. });
  9. },false)

fetch异步编程语法糖
asyncawait

  1. // async:声明此函数是异步任务
  2. window.addEventListener(
  3. "load",
  4. async () => {
  5. let url = "https://jsonplaceholder.typicode.com/users";
  6. // 异步耗时操作,需要等待结果才可进入下一步
  7. const response = await fetch(url);
  8. // 获取到结果之后,再转为json
  9. const result = await response.json();
  10. console.log(result);
  11. },
  12. false
  13. );

2.模块成员导出与导入,别名使用场景与命名空间演示

模板导出

  1. // 1.逐个导出
  2. export let userName = "张三";
  3. export let sex = "male";
  4. // 2.统一导出
  5. // (1)声明
  6. let hello = "hello";
  7. function getHello(hello, userName) {
  8. return `${hello}:${userName}`;
  9. }
  10. // (2)导出: 对象字面量 {...}
  11. export { hello, getHello };
  12. // 3.别名导出
  13. let prodName = "华为手机";
  14. let price = 5000;
  15. function prdoPrice(prodName, price) {
  16. return `手机:${prodName} , 价格:${price}`;
  17. }
  18. export { prodName as n, price as p, prdoPrice as fn };
  19. // 4.默认导出 只导出一个值 一个模块,只能有一个默认导出
  20. export default class {
  21. constructor(userName) {
  22. this.userName = userName;
  23. }
  24. getUserName() {
  25. return `Hello ${this.username}`;
  26. }
  27. }
  28. // 5.混合导出 默认成员和非默认成员
  29. // (1) 默认成员 第四点已导出
  30. // (2) 非默认成员
  31. let email = "1331440618@qq.com";
  32. // 私有成员, 不对外 不导出
  33. let userSex = "male";
  34. export { email };
  35. // 可以将邮箱 email 做为默认导出 , 起一个特殊的别名 default
  36. // export {email as default};

模板导入

  1. <!-- 默认script在浏览器环境下不支持模块,需要指定类型type="module" -->
  2. <script type="module">
  3. // 1.逐个(统一)导出 统一导入
  4. import { userName, sex, hello, getHello } from "./modules/m1.js";
  5. console.log(" 1.逐个(统一)导出 统一导入");
  6. console.log(`**userName: ${userName} , sex: ${sex} **
  7. ${getHello(hello, userName)}`);
  8. console.log(" ====================== ");
  9. // 2.别名导出 统一导入
  10. import { n, p, fn } from "./modules/m1.js";
  11. console.log(" 2.别名导出 统一导入: ");
  12. console.log(fn(n, p));
  13. console.log(" ====================== ");
  14. // 3.别名导出 别名导入
  15. import { n as prodName, p as price, fn as prodPrice } from "./modules/m1.js";
  16. console.log(" 3.别名导出 别名导入: ");
  17. console.log(prodPrice(prodName, price));
  18. console.log(" ====================== ");
  19. // 4.默认导出 在导入时重命名
  20. import getName from "./modules/m1.js";
  21. console.log(" 4.默认导出 在导入时重命名:");
  22. const getUserName = new getName("张三, 李四, 王二, 麻子");
  23. console.log(getUserName);
  24. console.log(" ====================== ");
  25. // 5.混合导入 默认导出重命名在前 后面跟上模板字面量
  26. import Name, { email } from "./modules/m1.js";
  27. console.log(" 5.混合导入 默认导出重命名在前:");
  28. console.log(new Name("张三, 李四"));
  29. console.log(email);
  30. console.log(" ====================== ");
  31. // 6.命名空间导入 把所有模块封装在命名空间中 用属性“.”的方式来使用
  32. import * as info from "./modules/m1.js";
  33. console.log(" 6.命名空间导入 ");
  34. console.log(info.userName);
  35. console.log(new info.default("李四, 张三"));
  36. </script>

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议