IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> ES6高阶总结 -> 正文阅读

[JavaScript知识库]ES6高阶总结

promise

Promise 是异步编程的一种解决方案,主要解决回调地狱的问题,因为有的需求需要先完成某一个步骤,再进行下一个步骤,或者下一个步骤需要上一个步骤的结果。

三种状态:

pending(进行中)、resolved | fulfilled(火狐)(已成功)和rejected(已失败)

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为resolved 和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

Promise.prototype.then()

示例:

const p= new Promise((resolve, reject)=> {
  // ... some code
  if (/* 异步操作成功 */){
    resolve('成功');
  } else {
    reject(error);
  }
})
 p.then((res)=> {
     console.log("成功回调",res);
 }, (err)=> {
     console.log("失败回调 ",err);
});
//输出"成功回调",成功  或者失败回调 ",失败原因,上一步执行完的结果或者传参,在下一步可以获取

示例2:

let promise = new Promise((resolve, reject) =>{
  console.log('Promise');
  resolve();
});

promise.then(()=> {
  console.log('resolved.');
});

console.log('Hi!');

//输出 Promise  Hi!  resolved
//Promise 新建后立即执行,所以首先输出的是Promise。
//然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出。

示例3:

const p1 = new Promise((resolve, reject)=> {
	reject(new Error())
});

const p2 = new Promise((resolve, reject)=> {
  resolve(p1);
})

> resolve可带普通参数给then回调,也可带对象。reject一般带Error对象的实例,表示抛出的错误

Promise.prototype.catch()

示例4

new Promise((resolve, reject) => {
  resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
}).catch(error=>  console.log(error));
//输出   2   1
 //调用resolve(1)以后,后面的console.log(2)还是会执行,并且会首先打印出来。
 //这是因为立即 resolved 的 Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。

.catch接受运行中抛出错误,建议总是使用catch()方法,因为可以接收所有promise运行时的错误
虽然使用reject也可以接受这个错误,但其只针对一个回调函数,catch可以获取所有回调的错误

Promise.prototype.finally()

finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。

promise.then(result => {···})
.catch(error => {···})
.finally(() => {···});

Promise.all()

有一种需求,即前面三个请求,全部完成以后,才能去完成第四个请求,这时候all方法就派上用场了。
Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
示例5:

const databasePromise =new Promise((resolve,reject)=>{
		//连接数据库
})

const booksPromise = databasePromise
  .then(findAllBooks);

const userPromise = databasePromise
  .then(getCurrentUser);

const  p  = Promise.all([
  booksPromise,
  userPromise
])
.then(([books, user]) => pickTopRecommendations(books, user));
  1. Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例
  2. booksPromise、userPromise的状态都变成resolved,p的状态才会变成resolved,返回值组成数组传递给p的回调函数
  3. 只要有一个一个结果返回的是rejected,p的状态都会变成rejected,并返回第一个状态为rejected的返回值作为回调函数的参数

如果回调函数内部定义了.catch(e => e);方法,则就算报错,也会返回resolved。

const p1 = new Promise((resolve, reject) => {
  resolve('hello');
}).then(result => result)
.catch(e => e);

const p2 = new Promise((resolve, reject) => {
  throw new Error('报错了');
}.then(result => result)
.catch(e => e);

Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
//输出  // ["hello", Error: 报错了]
//这种情况下,就算p1  p2有执行错误,还是会返回resolved。其错误在内部消化了

Promise.allSettled()

有时候,我们希望等到一组异步操作都结束了,不管每一个操作是成功还是失败,再进行下一步操作。但是,现有的 Promise 方法很难实现这个要求。Promise.all()方法只适合所有异步操作都成功的情况,如果有一个操作失败,就无法满足要求。

Promise.race()

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例,
与all的区别主要是:

const p = Promise.race([p1, p2, p3]);

只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

Promise.any()

参数实例有一个变成fulfilled状态,包装实例就会变成resolved状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。

Promise.resolve()

有时需要将现有对象转为 Promise 对象,Promise.resolve()方法就起到这个作用。

const jsPromise = Promise.resolve($.ajax('/whatever.json'));
  1. 上面代码将 jQuery 生成的deferred对象,转为一个新的 Promise 对象

  2. 如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。

  3. 参数根本就不是对象

const p = Promise.resolve('Hello');

p.then(function (s) {
  console.log(s)
});
// 输出Hello
  1. Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的
const p = Promise.resolve();
p.then(function () {
  // ...
});

Promise.reject()

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。

const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))

p.then(null, (s)=> {
  console.log(s)
});
// 出错了
Promise.reject('出错了')
.catch(e => {
  console.log(e === '出错了')
})
// true

Promise.try()

promise.catch()捕获所有同步和异步的错误。

Promise.try(() => database.users.get({id: userId}))
  .then(...)
  .catch(...)

Generator 函数

调用 Generator 函数和调用普通函数一样,在函数名后面加上()即可,但是 Generator 函数不会像普通函数一样立即执行,而是返回一个指向内部状态对象的指针,所以要调用遍历器对象Iterator 的 next 方法,指针就会从函数头部或者上一次停下来的地方开始执行。

function* func(){
 console.log("one");
 yield '1';
 console.log("two");
 yield '2'; 
 console.log("three");
 return '3';
}

f.next();
// one
// {value: "1", done: false}
f.next();
// two
// {value: "2", done: false}
f.next();
// three
// {value: "3", done: true}
f.next();
// {value: undefined, done: true}

第一次调用 next 方法时,从 Generator 函数的头部开始执行,先是打印了 one ,执行到 yield 就停下来,并将yield 后边表达式的值 ‘1’,作为返回对象的 value 属性值,此时函数还没有执行完, 返回对象的 done 属性值是 false。

第二次调用 next 方法时,同上步 。

第三次调用 next 方法时,先是打印了 three ,然后执行了函数的返回操作,并将 return 后面的表达式的值,作为返回对象的 value 属性值,此时函数已经结束,多以 done 属性值为true 。

第四次调用 next 方法时, 此时函数已经执行完了,所以返回 value 属性值是 undefined ,done 属性值是 true 。如果执行第三步时,没有 return 语句的话,就直接返回 {value: undefined, done: true}。

next 方法

一般情况下,next 方法不传入参数的时候,yield 表达式的返回值是 undefined 。当 next 传入参数的时候,该参数会作为上一步yield的返回值。

function* sendParameter(){
    var x = yield '2';
    console.log("one:" + x);
    var y = yield '3';
    console.log("two:" + y);
    console.log("total:" + (x + y));
}
next不传参
var sendp1 = sendParameter();
sendp1.next();
// {value: "2", done: false}
sendp1.next();
// one:undefined
// {value: "3", done: false}
sendp1.next();
// two:undefined
// total:NaN
// {value: undefined, done: true}
next传参
var sendp2 = sendParameter();
sendp2.next(10);
// {value: "2", done: false}
sendp2.next(20);
// one:20
// {value: "3", done: false}
sendp2.next(30);
// two:30
// total:50
// {value: undefined, done: true}

return 方法

return 方法返回给定值,并结束遍历 Generator 函数。
return 方法提供参数时,返回该参数;不提供参数时,返回 undefined

function* foo(){
    yield 1;
    yield 2;
    yield 3;
}
var f = foo();
f.next();
// {value: 1, done: false}
f.return("foo");
// {value: "foo", done: true}
f.next();
// {value: undefined, done: true}

async/await和 Generator 函数区别

异步操作,同步执行,属于ES7中的内容
async 函数是什么?一句话,它就是 Generator 函数的语法糖。
Generator 是ES6中的内容,说白了就是Generator 的升级版,

有一个 Generator 函数,依次读取两个文件

const gen = function* () {
  const f1 = yield readFile('/etc/fstab');
  const f2 = yield readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

上面代码的函数gen可以写成async函数,就是下面这样。

const asyncReadFile = async function () {
  const f1 = await readFile('/etc/fstab');
  const f2 = await readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

一比较就会发现,async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。

async函数对 Generator 函数的改进,体现在以下四点。
1)内置执行器。

Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。

asyncReadFile();
上面的代码调用了asyncReadFile函数,然后它就会自动执行,输出最后结果。这完全不像 Generator 函数,需要调用next方法,或者用co模块,才能真正执行,得到最后结果。

(2)更好的语义。

async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

(3)更广的适用性。

co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。

(4)返回值是 Promise。

async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。

进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。

async/await

async 是 ES7 才有的与异步操作有关的关键字

const p = async ()=>{

}

async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。
async 函数中可能会有 await 表达式,async 函数执行时,如果遇到 await 就会先暂停执行 ,等到触发的异步操作完成后,恢复 async 函数的执行并返回解析值。
例子:

function testAwait(){
   return new Promise((resolve) => {
       setTimeout(function(){
          console.log("testAwait");
          resolve();
       }, 1000);
   });
}
 
async function helloAsync(){
   await testAwait();
   console.log("helloAsync");
 }
helloAsync();
// testAwait
// helloAsync

await

await 操作符用于等待一个 Promise 对象, 它只能在异步函数 async function 内部使用。
await 后面通常是一个Promise 对象或者任何要等待的值,返回 Promise 对象的处理结果。如果等待的不是 Promise 对象,则返回该值本身。
例子:

function testAwait (x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}
 
async function helloAsync() {
  var x = await testAwait ("hello world");
  console.log(x); 
}
helloAsync ();
// hello world

ES6 模块化

ES6 的模块化分为导出(export) @与导入(import)两个模块。

  1. ES6 的模块自动开启严格模式,不管你有没有在模块头部加上 use strict;。
  2. 模块中可以导入和导出各种类型的变量,如函数,对象,字符串,数字,布尔值,类等。
  3. 每个模块都有自己的上下文,每一个模块内声明的变量都是局部变量,不会污染全局作用域。
  4. 每一个模块只加载一次(是单例的), 若再去加载同目录下同文件,直接从内存中读取。

export 与 import

let myName = "Tom";
let myAge = 20;
let myfn = function(){
    return "My name is" + myName + "! I'm '" + myAge + "years old."
}
let myClass =  class myClass {
    static a = "yeah!";
}
export { myName, myAge, myfn, myClass }//导出

import { myName, myAge, myfn, myClass } from "./test.js";  //导入
console.log(myfn());// My name is Tom! I'm 20 years old.
console.log(myAge);// 20
console.log(myName);// Tom
console.log(myClass.a );// yeah!

as的用法 export { myName as exportName } 将导出命别名

import 命令的特点

不允许import 的模块重新指向

import {a} from "./xxx.js"
a = {}; // error

单例模式:多次重复执行同一句 import 语句,那么只会执行一次,而不会执行多次。import 同一模块,声明不同接口引用,会声明对应变量,但只执行一次 import 。

export default 命令

  1. 在一个文件或模块中,export、import 可以有多个,export default 仅有一个
  2. export default 向外暴露的成员,可以使用任意变量来接收。
  3. 通过 export 方式导出,在导入时要加{ },export default 则不需要。
  4. export default 中的 default 是对应的导出接口变量。
const p  = new promise((resolve,reject)=>{
		return 1111
})
export default p

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-27 12:44:50  更:2021-10-27 12:45:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/11 14:55:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码