那些必会用到的 ES6 精粹(下)

简介: 那些必会用到的 ES6 精粹(下)

10. Promise 对象


Promise 是异步编程的一种解决方案。


Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。


Promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled 和从 pending 变为

rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)


const someAsyncThing = function(flag) {
  return new Promise(function(resolve, reject) {
    if(flag){
        resolve('ok');
    }else{
        reject('error')
    }
  });
};
someAsyncThing(true).then((data)=> {
  console.log('data:',data); // 输出 'ok'
}).catch((error)=>{
  console.log('error:', error); // 不执行
})
someAsyncThing(false).then((data)=> {
  console.log('data:',data); // 不执行
}).catch((error)=>{
  console.log('error:', error); // 输出 'error'
})


上面代码中,someAsyncThing 函数成功返回 ‘OK’, 失败返回 ‘error’, 只有失败时才会被 catch 捕捉到。


最简单实现:


// 发起异步请求
    fetch('/api/todos')
      .then(res => res.json())
      .then(data => ({ data }))
      .catch(err => ({ err }));


来看一道有意思的面试题:


setTimeout(function() {
  console.log(1)
}, 0);
new Promise(function executor(resolve) {
  console.log(2);
  for( var i=0 ; i<10000 ; i++ ) {
    i == 9999 && resolve();
  }
  console.log(3);
}).then(function() {
  console.log(4);
});
console.log(5);


这道题应该考察 JavaScript 的运行机制的。


首先先碰到一个 setTimeout,于是会先设置一个定时,在定时结束后将传递这个函数放到任务队列里面,因此开始肯定不会输出 1 。


然后是一个 Promise,里面的函数是直接执行的,因此应该直接输出 2 3 。


然后,Promise 的 then 应当会放到当前 tick 的最后,但是还是在当前 tick 中。

因此,应当先输出 5,然后再输出 4 。


最后在到下一个 tick,就是 1 。


答案: “2 3 5 4 1”


11. async 函数


ES2017 标准引入了 async 函数,使得异步操作变得更加方便。


async 函数的使用方式,直接在普通函数前面加上 async,表示这是一个异步函数,在要异步执行的语句前面加上 await,表示后面的表达式需要等待。async 是 Generator 的语法糖

  1. async 函数内部 return 语句返回的值,会成为 then 方法回调函数的参数。


async function f() {
  return 'hello world';
}
f().then(v => console.log(v))
// "hello world"


上面代码中,函数 f 内部 return 命令返回的值,会被 then 方法回调函数接收到。

  1. async 函数内部抛出错误,会导致返回的 Promise 对象变为 reject 状态。抛出的错误对象会被 catch 方法回调函数接收到。


async function f() {
  throw new Error('出错了');
}
f().then(
  result => console.log(result),
  error => console.log(error)
)
// Error: 出错了


  1. async 函数返回的 Promise 对象,必须等到内部所有 await 命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到 return 语句或者抛出错误。也就是说,只有 async 函数内部的异步操作执行完,才会执行 then 方法指定的回调函数。


下面是一个例子:


async function getTitle(url) {
  let response = await fetch(url);
  let html = await response.text();
  return html.match(/<title>([\s\S]+)<\/title>/i)[1];
}
getTitle('https://tc39.github.io/ecma262/').then(console.log('完成'))
// "ECMAScript 2017 Language Specification"


上面代码中,函数 getTitle 内部有三个操作:抓取网页、取出文本、匹配页面标题。只有这三个操作全部完成,才会执行 then 方法里面的 console.log。


  1. 在 vue 中,我们可能要先获取 token ,之后再用 token 来请求用户数据什么的,可以这样子用:


methods:{
        getToken() {
            return new Promise((resolve, reject) => {
                this.$http.post('/token')
                    .then(res => {
                        if (res.data.code === 200) {
                           resolve(res.data.data)
                        } else {
                            reject()
                        }
                    })
                    .catch(error => {
                        console.error(error);
                    });
            })
       },
       getUserInfo(token) {
            return new Promise((resolve, reject) => {
                this.$http.post('/userInfo',{
                        token: token
                    })
                    .then(res => {
                        if (res.data.code === 200) {
                           resolve(res.data.data)
                        } else {
                            reject()
                        }
                    })
                    .catch(error => {
                        console.error(error);
                    });
            })
       },
       async initData() {
            let token = await this.getToken()
            this.userInfo = this.getUserInfo(token)
       },
}


12. import 和 export


import 导入模块、export 导出模块
// example2.js  // 导出默认, 有且只有一个默认
export default const example2 = {
  name : 'my name',
  age : 'my age',
  getName  = function(){  return 'my name' }
}
//全部导入 // 名字可以修改
import people from './example2.js'
-------------------我是一条华丽的分界线---------------------------
// example1.js // 部分导出
export let name  = 'my name'
export let age  = 'my age'
export let getName  = function(){ return 'my name'}
// 导入部分 // 名字必须和 定义的名字一样。
import  {name, age} from './example1.js'
//有一种特殊情况,即允许你将整个模块当作单一对象进行导入
//该模块的所有导出都会作为对象的属性存在
import * as example from "./example1.js"
console.log(example.name)
console.log(example.age)
console.log(example.getName())
-------------------我是一条华丽的分界线---------------------------
// example3.js  // 有导出默认, 有且只有一个默认,// 又有部分导出
export default const example3 = {
  birthday : '2018 09 20'
}
export let name  = 'my name'
export let age  = 'my age'
export let getName  = function(){ return 'my name'}
// 导入默认与部分
import example3, {name, age} from './example1.js'


总结:


1.当用 export default people 导出时,就用 import people 导入(不带大括号)
2.一个文件里,有且只能有一个 export default。但可以有多个 export。
3.当用 export name 时,就用 import { name }导入(记得带上大括号)
4.当一个文件里,既有一个 export default people, 又有多个 export name 或者 export age 时,导入就用 import people, { name, age } 
5.当一个文件里出现 n 多个 export 导出很多模块,导入时除了一个一个导入,也可以用 import * as example


13. Class


对于 Class ,小汪用在 react 中较多。


13.1基本用法:


//定义类
class FunSum {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  sum() {
    console.log( this.x +this.y')
  }
}
// 使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致。
let f = new FunSum(10, 20);
f.sum() // 30


13.2 继承


class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 调用父类的constructor(x, y)
    this.color = color;
  }
  toString() {
    return this.color + ' ' + super.toString(); // 调用父类的toString()
  }
}


上面代码中,constructor 方法和 toString 方法之中,都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的 this 对象。


子类必须在 constructor 方法中调用 super 方法,否则新建实例时会报错。这是因为子类自己的 this 对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用 super 方法,子类就得不到 this 对象。


class Point { /* ... */ }
class ColorPoint extends Point {
  constructor() {
  }
}
let cp = new ColorPoint(); // ReferenceError


上面代码中,ColorPoint 继承了父类 Point,但是它的构造函数没有调用 super 方法,导致新建实例时报错。

相关文章
rtsp推流
rtsp推流
784 0
|
5月前
|
人工智能 自然语言处理 搜索推荐
JeecgBoot AI 应用开发平台,AIGC 功能介绍
JeecgBoot推出AIGC功能模块,包含AI应用开发平台与知识库问答系统,支持AI流程编排、模型管理、知识库训练及向量库对接。基于LLM大语言模型,提供智能对话、RAG检索增强生成等功能,兼容多种大模型(如DeepSeek、Qwen等)。平台结合低代码与AIGC,适用于复杂业务场景,支持快速原型到生产部署,助力用户打造个性化智能体,如“诗词达人”或“翻译助手”,并可嵌入第三方系统提升交互能力。项目开源,欢迎体验与交流。
201 0
JeecgBoot AI 应用开发平台,AIGC 功能介绍
|
自动驾驶 物联网 5G
什么是 5G 以及它如何工作?
【8月更文挑战第23天】
2402 0
|
SQL 安全 Linux
BUUCTF:Basic 解析(一)
BUUCTF:Basic 解析(一)
|
9月前
|
机器学习/深度学习 数据采集 算法
深度学习在图像识别中的应用与挑战
本文探讨了深度学习技术在图像识别领域的应用,重点分析了卷积神经网络(CNN)的基本原理、优势以及面临的主要挑战。通过案例研究,展示了深度学习如何提高图像识别的准确性和效率,同时指出了数据质量、模型泛化能力和计算资源等关键因素对性能的影响。
|
11月前
|
应用服务中间件 程序员 开发工具
mac下安装nginx
mac下安装nginx
|
11月前
|
JavaScript UED
Vue双向数据绑定的原理
【10月更文挑战第7天】
|
Android开发 Kotlin
No signature of method: build_dr75kj88i2pi195a6zalvt5yu.android() is applicable for argument types
No signature of method: build_dr75kj88i2pi195a6zalvt5yu.android() is applicable for argument types
470 0
|
中间件 开发者 C++
Django中间件探索:揭秘中间件在Web应用中的守护角色与实战应用
Django中间件探索:揭秘中间件在Web应用中的守护角色与实战应用
|
C++
每日练习之——背包问题
每日练习之——背包问题
76 1