前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Promise 概述

Promise 概述

作者头像
心谭博客
发布2020-04-20 15:39:42
4310
发布2020-04-20 15:39:42
举报
文章被收录于专栏:YuanXinYuanXin

本文介绍了 Promise 的常用 API。

关于Promise

  • Promise实例一旦被创建就会被执行
  • Promise过程分为两个分支:pending=>resolvedpending=>rejected
  • Promise状态改变后,依然会执行之后的代码:
代码语言:javascript
复制
const warnDemo = ctx => {
    const promise = new Promise(resolve => {
        resolve(ctx);
        console.log("After resolved, but Run"); // 依然会执行这个语句
    });
    return promise;
};

warnDemo("ctx").then(ctx => console.log(`This is ${ctx}`));

then方法

Console键入以下内容:

代码语言:javascript
复制
let t = new Promise(() => {});
t.__proto__;

可以看到,then方法是定义在原型对象Promise.prototype上的。

then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。

写法
代码语言:javascript
复制
function func(args) {
    // 必须返回一个Promise实例
    return new Promise((resolve,reject)=>{
        if(...){
            resolve(...) // 传入resolve函数的参数
        } else {
            let err = new Error(...)
            reject(err) // reject参数必须是Error对象
        }
    })
}

func(ARGS).then(()=>{
    // resolve 函数
},()=>{
    // reject 函数
})
连续调用then

因为then方法返回另一个Promise对象。当这个对象状态发生改变,就会分别调用resolvereject

写法如下:

代码语言:javascript
复制
func(ARGS).then(()=>{
    ...
}).then(
    ()=>{ ... },
    () => { ... }
)
实例
代码语言:javascript
复制
function helloWorld(ready) {
    return new Promise((resolve, reject) => {
        if (ready) {
            resolve("Right");
        } else {
            let error = new Error("arg is false");
            reject(error); // 传入Error对象
        }
    });
}

helloWorld(false).then(
    msg => {
        // true:helloWorld的参数
        // 参数msg:在上面的Promise对象中传入了
        console.log(msg);
    },
    error => {
        console.log(error.message);
    }
);

catch方法

等同于 .then(null, rejection)。另外,then方法指定的回调函数运行中的错误,也会被catch捕获。

所以,之前的写法可以改为:

代码语言:javascript
复制
function func(args) {
    // 必须返回一个Promise实例
    const promise =  new Promise((resolve,reject)=>{
        if(...){
            resolve(...)
        } else {
            let err = new Error(...)
            reject(err)
        }
    })
    return promise
}

func(ARGS).then(()=>{
    // resolve 函数
}).catch(()=>{
    // reject 函数
}).then(()=>{
    // 没有错误就会跳过上面的catch
})...

finally方法

指定不管 Promise 对象最后状态如何,都会执行的操作。可以理解为then方法的实例,即在resolvereject里面的公共操作函数

all方法

用于将多个 Promise 实例,包装成一个新的 Promise 实例。它接收一个具有Iterator接口的参数。其中,item如果不是Promise对象,会自动调用Promise.resolve方法

以下代码:

代码语言:javascript
复制
const p = Promise.all([p1, p2, p3]); // p是新包装好的一个Promise对象

对于Promise.all()包装的Promise对象,只有实例的状态都变成fulfilled

可以用来操作数据库:

代码语言:javascript
复制
const databasePromise = connectDatabase();

const booksPromise = databasePromise.then(findAllBooks);

const userPromise = databasePromise.then(getCurrentUser);

Promise.all([booksPromise, userPromise]).then(([books, user]) =>
    pickTopRecommentations(books, user)
);

或者其中有一个变为rejected,才会调用Promise.all方法后面的回调函数。而对于每个promise对象,一旦它被自己定义catch方法捕获异常,那么状态就会更新为resolved而不是rejected

代码语言:javascript
复制
"use strict";
const p1 = new Promise((resolve, reject) => {
    resolve("hello");
})
    .then(result => result)
    .catch(e => e);

const p2 = new Promise((resolve, reject) => {
    throw new Error("p2 error");
})
    .then(result => result)
    .catch(
        // 如果注释掉 catch,进入情况2
        // 否则,情况1
        e => e.message
    );

Promise.all([p1, p2])
    .then(
        result => console.log(result) // 情况1
    )
    .catch(
        e => console.log("error in all") // 情况2
    );

race方法

all方法类似,Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。而且只要有一个状态被改变,那么新的Promise状态会立即改变

也是来自阮一峰大大的例子,如果 5 秒内无法fetech,那么p状态就会变为rejected

代码语言:javascript
复制
const p = Promise.race([
    fetch("/resource-that-may-take-a-while"),
    new Promise(function(resolve, reject) {
        setTimeout(() => reject(new Error("request timeout")), 5000);
    })
]);
p.then(response => console.log(response));
p.catch(error => console.log(error));

重要性质

状态只改变一次

Promise 的状态一旦改变,就永久保持该状态,不会再变了。

下面代码中,Promise对象resolved后,状态就无法再变成rejected了。

代码语言:javascript
复制
"use strict";

const promise = new Promise((resolve, reject) => {
    resolve("ok"); // 状态变成 resolved
    throw new Error("test"); // Promise 的状态一旦改变,就永久保持该状态
});
promise
    .then(val => {
        console.log(val);
    })
    .catch(error => {
        console.log(error.message); // 所以,无法捕获错误
    });

错误冒泡

Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获

“吃掉错误”机制

Promise会吃掉内部的错误,并不影响外部代码的运行。所以需要catch,以防丢掉错误信息。

阮一峰大大给出的 demo:

代码语言:javascript
复制
"use strict";

const someAsyncThing = function() {
    return new Promise(function(resolve, reject) {
        // 下面一行会报错,因为x没有声明
        resolve(x + 2);
    });
};

someAsyncThing().then(function() {
    console.log("everything is great");
});

setTimeout(() => {
    console.log(123);
}, 2000);

还有如下 demo

代码语言:javascript
复制
someAsyncThing()
    .then(function() {
        return someOtherAsyncThing();
    })
    .catch(function(error) {
        console.log("oh no", error);
        // 下面一行会报错,因为y没有声明
        y + 2;
    })
    .catch(function(error) {
        console.log("carry on", error);
    });
// oh no [ReferenceError: x is not defined]
// carry on [ReferenceError: y is not defined]

参考

  • demo 基本可以在阮一峰的 Es6 讲解中找到,只是为了理解做了一些修改。
  • 还有网上的一些博客,这里就不一一说明了
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-05-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于Promise
  • then方法
    • 写法
      • 连续调用then
        • 实例
        • catch方法
        • finally方法
        • all方法
        • race方法
        • 重要性质
          • 状态只改变一次
            • 错误冒泡
              • “吃掉错误”机制
              • 参考
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档