第125篇: 期约Promise基本特性

期约,promise,基本,特性 · 浏览次数 : 61

小编点评

**期约与异步函数** **1.非重入期约** **1.1 可重入代码** 可重入代码是指允许多个进程同时访问的代码。为了使各进程所执行的代码完全相同,故不允许任何进程对其进行修改。程序在运行过程中可以被打断,并由开始处再次执行,并且在合理的范围内(多次重入,而不造成堆栈溢出等其他问题),程序可以在被打断处继续执行,且执行结果不受影响。 **1.2 非重入期约非重入期约方法** 期约进入 落定(解决/拒绝)状态时,与该状态相关的处理程序不会立即执行 ,处理程序后的 同步代码 会在其之前先执行 ,该特性称为非重入当期约进入落定状态时,与该状态相关的处理程序仅仅会被排期,而非立即执行。跟在添加这个处 理程序的代码之后的同步代码一定会在处理程序之前先执行。即使期约一开始就是与附加处理程序关联 的状态,执行顺序也是这样的。这个特性由 JavaScript 运行时保证,被称为“非重入”(non-reentrancy) 特性。 **2.邻近处理程序的执行顺序** 当期约添加了多个处理程序,当期约状态变化时,相关处理程序会按照添加它们的顺序依次执行。 **3.期约连锁** 期约合成这肯定是个将多个期约合成为一个的某个特性(废话)Promise 类提供两个将多个期约实例组合成一个期约的静态方法:`Promise.all()`和 `Promise.race()`. **4.期约合成** 4.1 `Promise.all()`特性一:合成的期约只会在每个包含的期约都解决之后才解决特性二:如果至少有一个包含的期约待定,则合成的期约也会待定。如果有一个包含的期约拒绝,则合成的 期约也会拒绝 **4.2 `Promise.race()` Promise.race()不会对解决或拒绝的期约区别对待。无论是解决还是拒绝,只要是第一个落定的 期约,Promise.race()就会包装其解决值或拒绝理由并返回新期约

正文

好家伙,本篇为《JS高级程序设计》第十章“期约与异步函数”学习笔记

 

1.非重入期约

1.1.可重入代码(百度百科)

先来了解一个概念

可重入代码(Reentry code)也叫纯代码(Pure code)是一种允许多个进程同时访问的代码。

为了使各进程所执行的代码完全相同,故不允许任何进程对其进行修改。

程序在运行过程中可以被打断,并由开始处再次执行,并且在合理的范围内(多次重入,而不造成堆栈溢出等其他问题),

程序可以在被打断处继续执行,且执行结果不受影响。

                                            ----来自百度百科

 

1.2.非重入期约

非重入期约方法 期约进入 落定(解决/拒绝)状态时,与该状态相关的处理程序不会立即执行 ,

处理程序后的 同步代码 会在其之前 先执行 ,该特性称为非重入

当期约进入落定状态时,与该状态相关的处理程序仅仅会被排期,而非立即执行。

跟在添加这个处 理程序的代码之后的同步代码一定会在处理程序之前先执行。

即使期约一开始就是与附加处理程序关联 的状态,执行顺序也是这样的。

这个特性由 JavaScript 运行时保证,被称为“非重入”(non-reentrancy) 特性。

 

let promise = new Promise(() => {
    console.log("5")
})

// 创建一个期约并将解决函数保存在一个局部变量中
let p = new Promise((resolve) => {
    synchronousResolve = function () {
        console.log('1');
        resolve();
        console.log('2');
    };
    synchronousResolve();
});
p.then(() => console.log('4'));
console.log('3');

 

看到了吗,这里4依旧被放在了最后输出

这说明在这个例子中,即使期约状态变化发生在添加处理程序之后,处理程序也会等到运行的消息队列让 它出列时才会执行。

 

 

 

2.邻近处理程序的执行顺序

如果给期约添加了多个处理程序,当期约状态变化时,相关处理程序会按照添加它们的顺序依次执行

let p1 = Promise.resolve(); 
p1.then(() => setTimeout(console.log, 0, 1)); 
p1.then(() => setTimeout(console.log, 0, 2)); 
p1.then(() => setTimeout(console.log, 0, 3)); 
p1.then(() => setTimeout(console.log, 0, 4)); 

 

 

 

 

3.期约连锁

把期约逐个地串联起来是一种非常有用的编程模式。

之所以可以这样做,是因为每个期约实例的方 法(then()、catch()和 finally())都会返回一个新的期约对象,

而这个新期约又有自己的实例方,这样连缀方法调用就可以构成所谓的“期约连锁”

你应该能想象到,这就是一长串then(),( then()、catch()和 finally()都行 )

let p = new Promise((resolve, reject) => {
    resolve();
});
p.then(() => console.log('1'))
    .then(() => console.log('2'))
    .then(() => console.log('3'))
    .then(() => console.log('4'));

 

 

 

 

4.期约合成

这肯定是个将多个期约合成为一个的某个特性(废话)

Promise 类提供两个将多个期约实例组合成一个期约的静态方法:Promise.all()和 Promise.race()。

而合成后期约的行为取决于内部期约的行为。


4.1.Promise.all()

特性一:合成的期约只会在每个包含的期约都解决之后才解决

特性二:如果至少有一个包含的期约待定,则合成的期约也会待定。

如果有一个包含的期约拒绝,则合成的 期约也会拒绝

let p1 = Promise.all([
    Promise.resolve(),
    new Promise((resolve, reject) => {
        resolve();
    })
]);
console.log("I'm p1");
console.log(p1);

// 一次拒绝会导致最终期约拒绝
let p2 = Promise.all([
    Promise.resolve(),
    Promise.reject(),
    Promise.resolve()
]);
console.log("I'm p2");
console.log(p2);

let p3 = Promise.all([
    Promise.resolve(),
    new Promise(() => {}),
    Promise.resolve()
]);
console.log("I'm p3");
console.log(p3);

 

 

 

 

4.2.Promise.race()

Promise.race()不会对解决或拒绝的期约区别对待。

无论是解决还是拒绝,只要是第一个落定的 期约,Promise.race()就会包装其解决值或拒绝理由并返回新期约

let p1 = Promise.race([
    Promise.resolve(),
    new Promise((resolve, reject) => {
        resolve();
    })
]);
console.log("I'm p1");
console.log(p1);

// 一次拒绝会导致最终期约拒绝
let p2 = Promise.race([
    Promise.resolve(),
    Promise.reject(),
    Promise.resolve()
]);
console.log("I'm p2");
console.log(p2);

let p3 = Promise.race([
    Promise.resolve(),
    new Promise(() => {}),
    Promise.resolve()
]);
console.log("I'm p3");
console.log(p3);

 

 

 

 

5.课后练习

 

1.什么是promise期约连锁?

  答:Promise期约连锁调用是使用Promise的一种技术,它可以让你把多个Promise以链式的方式组合起来,每个Promise的结果作为下一个Promise的输入。

这样可以把复杂的操作分解成一系列简单的操作,以便更容易理解和管理。

 

2.如何解释Promise的的非重入特性?

  答:非重入期约方法 期约进入 落定(解决/拒绝)状态时,与该状态相关的处理程序不会立即执行 ,

 

处理程序后的 同步代码 会在其之前 先执行 ,该特性称为非重入

 

与第125篇: 期约Promise基本特性相似的内容:

第125篇: 期约Promise基本特性

好家伙,本篇为《JS高级程序设计》第十章“期约与异步函数”学习笔记 1.非重入期约 1.1.可重入代码(百度百科) 先来了解一个概念 可重入代码(Reentry code)也叫纯代码(Pure code)是一种允许多个进程同时访问的代码。 为了使各进程所执行的代码完全相同,故不允许任何进程对其进行修

第121篇: DOM常用类型(Document、Element)

好家伙,本篇为《JS高级程序设计》第十四章“DOM编程”学习笔记 1.Document类型 Document 类型是 JavaScript 中表示文档节点的类型。 在浏览器中,文档对象 document 是 HTMLDocument 的实例(HTMLDocument 继承 Document),表示整

LeetCode 双周赛 99,纯纯送分场!

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问。 大家好,我是小彭。 昨晚是 LeetCode 第 99 场双周赛,你参加了吗?这场周赛整体难度很低,第 4 题评论区普遍认为是 1 字头,纯纯手速场。 小彭的 Android 交流群 02 群来了,公众号回复

第一百零五篇:变量的原始值和引用值

好家伙,JS基础接着学, 本篇内容为《JS高级程序设计》第四章学习笔记 1.原始值和引用值 ECMAScript变量可以包含两种不同类型的数据:原始值和引用值。原始值(primitive value)就是最简单的数据,引用值(reference value)则是由多个值构成的对象。 在把一个值赋给变

第一百零六篇:变量的不同声明(var,let和const的不同)

JS关于变量的声明,变量提升,暂时性死区

第一百零七篇:基本数据类型(undefined,null,boolean类型)

好家伙, 本篇内容为《JS高级程序设计》第三章学习笔记 1.数据类型 ECMAScript有6种简单数据类型(称为原始类型): Undefined, Null, Boolean, Number, String和Symbol。 Symbol (符号)是ECMAScript6新增的。还有一种复杂数据类型

第一百零八篇:最常用的基本数据类型(Number类型)

最常用的基本数据类型(Number类型)

第一百一十篇:内存泄漏和垃圾回收(JS)

好家伙,本篇内容为《JS高级程序设计》第四章的学习笔记 1.内存泄露 1.1.什么是内存泄漏? 内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。 内存泄漏缺陷具有隐蔽性、积累性的特征,比其

第一百一十一篇:基本引用类型Date

好家伙,本篇为《JS高级程序设计》第五章的学习笔记 1.基本引用类型 引用值(或者对象)是某个特定引用类型的实例,在ECMAScript中,引用类型是把数据和功能组织到一起的结构,(像极了“类”) 经常被人错误的称作“类”。 虽然从技术上讲JavaScript是一门面向对象语言,但是ECMAScri

第一百一十二篇: JS数组Array(一)数组基本用法

好家伙, 1.数组 Array应该就是ECMAScript中最常用的类型了。ECMAScript数组跟其他编程语言的数组有很大区别。 跟其他语言中的数组一样,ECMAScript 数组也是一组有序的数据, 但跟其他语言不同的是,数组中每个槽位可以存储任意类型的数据。 这意味着可以创建一个数组,它的第