Iwen's blog Iwen's blog
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于

Iwen

不摸鱼的哥哥
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于
  • Vue

  • Vue进阶

  • CSS

  • ES6

  • Base

  • Core

  • Array

  • Object

  • String

  • Async

    • Ajax
    • Promise
      • then()
      • catch()
      • finally()
      • all()
      • race()
      • allSettled()
      • 参考
    • Promise 回调
    • async await
    • 跨域
    • try catch
    • Generator async await原理
  • Browser

  • Http

  • 性能优化

  • 正则

  • 经典总结

  • 设计模式

  • 数据结构

  • 算法

  • 手写

  • TypeScript

  • 复盘
  • Async
Mr.w
2020-11-29

Promise

# Promise 方法

Promise 中的执行函数是同步进行的,但是里面存在着异步操作,在异步操作结束后会调用 resolve 方法,或者中途遇到错误调用 reject 方法,这两者都是作为微任务进入到 EventLoop 中。

下面的例子,来了解同步和异步

console.log(1)
let promiseDemo = new Promise((resolve, reject) => {
    console.log(2)
    let random = Math.random()
    if (random >= 0.2) {
        resolve('success')
        console.log(3)
    } else {
        reject('failed')
        console.log(3)
    }   
})
console.log(8)
async function test() {
    console.log(4)
    let result = await promiseDemo
    return result
}
setTimeout(() => {
    console.log(7)
}, 0)
test().then(result => {
    console.log(5)
}).catch((result) => {
    console.log(5)
})

console.log(6)

// 1 2 3 8 4 6 7 5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# then()

用于成功时的回调函数。

# catch()

用于指定发生错误时的回调函数。

一般来说,不要在then()方法里面定义 Reject 状态的回调函数(即then的第二个参数),总是使用catch方法。

// bad
promise
    .then(function(data) {
        // success
    }, function(err) {
        // error
    });

// good
promise
    .then(function(data) {
        // success
    })
    .catch(function(err) {
        // error
    });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# finally()

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

finally方法的回调函数不接受任何参数,方法里面的操作,是与状态无关的,不依赖于Promise的执行结果。

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

promise
    .finally(() => {
    // 语句
    });

// 等同于
promise
    .then(
        result => {
            // 语句
            return result;
        },
        error => {
            // 语句
            throw error;
        }
    );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

上面代码中,如果不使用finally方法,同样的语句需要为成功和失败两种情况各写一次。有了finally方法,则只需要写一次。

# all()

方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

只有Promise1、Promise2、Promise3的状态都变成fulfilled,p的状态才会变成fulfilled,此时Promise1、Promise2、Promise3的返回值组成一个数组,传递给p的回调函数。

只要Promise1、Promise2、Promise3之中有一个被rejected,p的状态才会变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

let Promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        var num = Math.ceil(Math.random()*10); //生成1-10的随机数
        if(num <= 5){
            resolve(num);
        }
        else{
            reject('数字太大了');
        }
    }, 2000)
})
let Promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        var num = Math.ceil(Math.random()*10); //生成1-10的随机数
        if(num <= 5){
            resolve(num);
        }
        else{
            reject('数字太大了');
        }
    }, 2000)
})
let Promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        var num = Math.ceil(Math.random()*10); //生成1-10的随机数
        if(num <= 5){
            resolve(num);
        }
        else{
            reject('数字太大了');
        }
    }, 2000)
})

let p = Promise.all([Promise1, Promise2, Promise3])

p.then((res) => {
    // 三个都成功则成功  
    console.log('resolved', res)
}).catch((err) => {
    // 只要有失败,则失败 
    console.log('rejectd', err)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

适合使用的场景,在所有异步方法都执行完毕后,再执行某一方法。

# race()

接收数组,方法返回一个promise,一旦迭代器中的某个promise解决或拒绝,返回的promise就会解决或拒绝。

race就是竞争的意思,数组内的Promise实例,谁执行的快,就返回谁的执行结果,不管是成功还是失败

var p1 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 500, "one"); 
});
var p2 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 100, "two"); 
});

Promise.race([p1, p2]).then(function(value) {
    console.log(value); // "two"
    // 两个都完成,但 p2 更快
});

var p3 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 100, "three");
});
var p4 = new Promise(function(resolve, reject) { 
    setTimeout(reject, 500, "four"); 
});

Promise.race([p3, p4]).then(function(value) {
    // p3 更快,所以它完成了              
    console.log(value); // "three"
}, function(reason) {
    // 未被调用
});

var p5 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 500, "five"); 
});
var p6 = new Promise(function(resolve, reject) { 
    setTimeout(reject, 100, "six");
});

Promise.race([p5, p6]).then(function(value) {
    // 未被调用             
}, function(reason) {
    console.log(reason); // "six" p6 更快,所以它失败了
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# allSettled()

接受一组 Promise 实例作为参数,包装成一个新的Promise实例。只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束。该方法由 ES2020 引入。

该方法返回的新的Promise实例,一旦结束,状态总是fulfilled,不会变成rejected。

状态变成fulfilled后,Promise的监听函数接收到的参数是一个数组,每个成员对应一个传入Promise.allSettled()的Promise实例。

const resolved = Promise.resolve(42);
const rejected = Promise.reject(-1);

const allSettledPromise = Promise.allSettled([resolved, rejected]);

allSettledPromise.then((results) => {
  console.log(results);  
});
// [{status: "fulfilled", value: 42}, {status: "rejected", reason: -1}]
1
2
3
4
5
6
7
8
9

# 参考

  • Promise不会??看这里!!!史上最通俗易懂的Promise!!! (opens new window)
  • BAT前端经典面试问题:史上最最最详细的手写Promise教程 (opens new window)
  • 从零开始写一个符合Promises/A+规范的promise (opens new window)
  • Promise实现原理(附源码) (opens new window)
Ajax
Promise 回调

← Ajax Promise 回调→

最近更新
01
flex布局页面自适应滚动条问题
12-28
02
前后端分离开发请求接口跨域如何携带cookie的问题
12-28
03
怎么实现div长宽比固定width-height4比3
12-28
更多文章>
Theme by Vdoing | Copyright © 2017-2022 Iwen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式