Blog
首页
文档
收藏
关于
  • 在线转换时间戳 (opens new window)
  • 在线压缩图片 (opens new window)
  • Float-Double转二进制 (opens new window)
  • 文件转Hex字符串 (opens new window)

HiuZing

🍑
首页
文档
收藏
关于
  • 在线转换时间戳 (opens new window)
  • 在线压缩图片 (opens new window)
  • Float-Double转二进制 (opens new window)
  • 文件转Hex字符串 (opens new window)
  • 前端面试题

  • JavaScript

    • JavaScript语法

      • JavaScript-数据类型
      • JavaScript-ES6编程风格
      • JavaScript-异步编程
      • JavaScript-Promise
        • JavaScript-Promise
          • Promise基本语法
          • 构造 Promise
          • Promise 的使用
          • Promise 常见问题
          • Promise API
          • async await
      • JavaScript-Proxy
      • JavaScript-Reflect
      • JavaScript-Iterator
      • JavaScript-Module
      • JavaScript-拷贝
      • JavaScript-this
      • JavaScript-垃圾回收机制
      • JavaScript-闭包
      • let和const
      • JavaScript-参数默认值
      • JavaScript-rest
      • JavaScript-扩展运算符
      • JavaScript-Symbol
      • JavaScript-生成器
      • JavaScript-class类
      • JavaScript-数值扩展
      • JavaScript-高阶函数
      • JavaScript-箭头函数
    • JavaScipt对象

    • JavaScript实例

    • JavaScript浏览器BOM

    • JavaScript DOM

  • Vue2

  • port

  • CSS

  • Node.js

  • JavaScript优化

  • uniapp

  • Mini Program

  • TypeScript

  • 面向对象编程

  • UI组件

  • Plugin

  • Vue3

  • 性能优化

  • Axios

  • 状态管理

  • React

  • Mock

  • Icon

  • Template

  • 构建工具

  • 项目规范配置

  • Taro

  • SVG

  • React Native

  • 前端
  • JavaScript
  • JavaScript语法
HiuZing
2022-10-08
目录

JavaScript-Promise

# JavaScript-Promise

Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。

Promise 是 ES6引入的异步编程的新解决方案。语法上 Promise 是一个构造函数用来封装异步操作并可以获取其成功或失败的结果。

  1. Promise 构造函数: Promise(excutor)
  2. Promise.prototype.then 方法
  3. Promise.prototype.catch 方法

# Promise基本语法

// 实例化 Promise对象
const p = new Promise(function(resolve,reject){
    setTimeout(function(){
        // 成功的数据
        // let data = '用户数据'
        // resolve(data)
        
        // 失败的数据
        let err = '数据读取失败'
        reject(err)
    },1000)
})
p.then(function(value){
    console.log(value) // 用户数据
},function(reason){
    console.log(reason) // 数据读取失败
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

需求:如果我想分三次输出字符串,第一次间隔 1 秒,第二次间隔 4 秒,第三次间隔 3 秒:

setTimeout(function () {
    console.log("First");
    setTimeout(function () {
        console.log("Second");
        setTimeout(function () {
            console.log("Third");
        }, 3000);
    }, 4000);
}, 1000);

// First
// Second
// Third
1
2
3
4
5
6
7
8
9
10
11
12
13

# 构造 Promise

现在我们用 Promise 来实现上面的功能:

new Promise(function (resolve, reject) {
    setTimeout(function () {
        console.log("First");
        resolve();
    }, 1000);
}).then(function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log("Second");
            resolve();
        }, 4000);
    });
}).then(function () {
    setTimeout(function () {
        console.log("Third");
    }, 3000);
});

// First
// Second
// Third
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# Promise 的使用

Promise 构造函数只有一个参数,是一个函数

这个函数在构造之后会直接被异步运行,所以我们称之为起始函数

起始函数包含两个参数 resolve 和 reject

resolve 和 reject 都是函数,其中调用 resolve 代表一切正常,reject 是出现异常时所调用的:

new Promise(function (resolve, reject) {
    console.log('run')
    var a = 0;
    var b = 1;
    if (b === 0) reject("Divide zero");
    else resolve(a / b);
}).then(function (value) {
    console.log("a / b = " + value);
}).catch(function (err) {
    console.log(err);
}).finally(function () {
    console.log("End");
});

// run
// a / b = 0
// End      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# Promise 常见问题

Q: 什么时候适合用 Promise 而不是传统回调函数?

A: 当需要多次顺序执行异步操作的时候,例如,如果想通过异步方法先后检测用户名和密码,需要先异步检测用户名,然后再异步检测密码的情况下就很适合 Promise。

Q: Promise 是一种将异步转换为同步的方法吗?

A: 完全不是。Promise 只不过是一种更良好的编程风格。

# Promise API

# Promise.all()

该方法的作用是将多个 promise 对象实例包装,生成并返回一个新的 promise 实例。返回值将会按照参数内的 promise 顺序排列,而不是由调用 promise 的完成顺序决定。

都成功-->成功

有一个失败-->失败

成功结果-->是几个promise对象成功结果组成的结果

失败结果-->有一个失败的promise结果的结果

只适合所有异步操作都成功的情况,如果有一个操作失败,就无法满足要求。

var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([p1, p2, p3]).then(values => {
  console.log(values); // [3, 1337, "foo"]
});
1
2
3
4
5
6
7
8
9

# Promise.race()

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

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

# Promise.allSettled()

有时候,我们希望等到一组异步操作都结束了,不管每一个操作是成功还是失败,再进行下一步操作。

Promise.all()可以确定所有请求都成功了,但是只要有一个请求失败,它就会报错,而不管另外的请求是否结束

ES2020 (opens new window) 引入了Promise.allSettled()方法,用来确定一组异步操作是否都结束了(不管成功或失败)。所以,它的名字叫做Settled,包含了fulfilled和rejected两种情况

const promises = [
  fetch('/api-1'),
  fetch('/api-2'),
  fetch('/api-3'),
];

await Promise.allSettled(promises);
removeLoadingIndicator();

// 数组promises包含了三个请求,只有等到这三个请求都结束了(不管请求成功还是失败),removeLoadingIndicator()才会执行。
1
2
3
4
5
6
7
8
9
10

# Promise.any()

该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回

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

Promise.any()跟Promise.race()方法很像,只有一点不同,就是Promise.any()不会因为某个 Promise 变成rejected状态而结束,必须等到所有参数 Promise 变成rejected状态才会结束。

const promises = [
  fetch('/endpoint-a').then(() => 'a'),
  fetch('/endpoint-b').then(() => 'b'),
  fetch('/endpoint-c').then(() => 'c'),
];

try {
  const first = await Promise.any(promises);
  console.log(first);
} catch (error) {
  console.log(error);
}
1
2
3
4
5
6
7
8
9
10
11
12

Promise.any()方法的参数数组包含三个 Promise 操作。其中只要有一个变成fulfilled,Promise.any()返回的 Promise 对象就变成fulfilled。如果所有三个操作都变成rejected,那么await命令就会抛出错误

# Promise.try()

实际开发中,经常遇到一种情况:不知道或者不想区分,函数f是同步函数还是异步操作,但是想用 Promise 来处理它。

因为这样就可以不管f是否包含异步操作,都用then方法指定下一步流程,用catch方法处理f抛出的错误。

const f = () => console.log('now');
Promise.try(f);
console.log('next');
// now
// next
1
2
3
4
5

# async await

异步函数 async function 中可以使用 await 指令,await 指令后必须跟着一个 Promise,异步函数会在这个 Promise 运行中暂停,直到其运行结束再继续运行。

异步函数实际上原理与 Promise 原生 API 的机制是一模一样的,只不过更便于程序员阅读。

function print(delay, message) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log(message);
            resolve();
        }, delay);
    });
}

// Promise 函数
print(1000, "First").then(function () {
    return print(4000, "Second");
}).then(function () {
    print(3000, "Third");
});

// async 函数
async function asyncFunc() {
    await print(1000, "First");
    await print(4000, "Second");
    await print(3000, "Third");
}
asyncFunc();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
上次更新: 2024/08/14, 04:14:33
JavaScript-异步编程
JavaScript-Proxy

← JavaScript-异步编程 JavaScript-Proxy→

最近更新
01
React Native 使用SVG
08-13
02
Docker基础命令
08-04
03
算数逻辑单元
07-30
更多文章>
Theme by Vdoing | Copyright © 2021-2024 WeiXiaojing | 友情链接
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式