JavaScript Promise对象

前言

When we learn a new technology,we need to know what it is,why we learn it and how to use it best

​ Promise对象,在如今的JavaScript编程中,使用的次数是非常多的。因此,若想要真正掌握好JavaScript(在这里主要是讲es6语法),那么对于Promise对象的使用必须是十分熟悉的。

​ Promise对象是es6新出的语法,创建该对象的主要目的是为了实现JavaScript的异步操作。

​ 这篇文章也就简单讲述一下本人对于es6中的Promise对象的理解

什么是Promise对象

​ 在我们学习Promise对象时,我们必须要清楚它是什么东西

​ Promise对象,其实本质上是一个函数,那么它是可以执行Function上的一些方法(call,apply,bind…)。从另外一个方面来讲,Promise对象其实是一个容器,在这个容器中我们可以去完成一些任务,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

Promise对象类型

​ 那么,Promise对象究竟是什么东西,这里有两个定义

  1. 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。(网址:http://es6.ruanyifeng.com/#docs/promise)
  2. Promise 对象用于表示一个异步操作的最终完成 (或失败), 及其结果值。(网址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise)

​ 在我看来,Promise对象其实就是用于处于异步操作的函数。我们可以通过使用Promise对象来完成异步。至于如何使用Promise对象,后面会有提到。

为什么会出现Promise对象

​ Promise对象的出现其实是为了解决回调函数的“回调地狱”问题(关于回调地狱的相关问题可以阅读这篇文章:https://www.cnblogs.com/suihang/p/9595548.html)。

​ 主要原因是如果我们使用回调函数的方法来进行异步操作,我们书写的代码的阅读性会变得非常的糟糕,而使用Promise对象就可以使我们编写的代码更加方便开发人员阅读(主要是因为Promise的链式调用)

Promise对象的基本认识

​ 接下来,就是来说说Promise对象的一些基本概念。

注意:我们要搞清楚我们应该什么时候使用Promise对象(一般只要我们需要异步操作的时候都可以使用Promise对象)。不要因为去使用Promise对象而去使用Promise对象

Promise对象在执行开始到执行完成有以下几种状态

  1. pending: 初始状态,既不是成功,也不是失败状态。
  2. fulfilled: 意味着操作成功完成。
  3. rejected: 意味着操作失败。

​ pending 状态的 Promise 对象可能会变为fulfilled 状态并传递一个值给相应的状态处理方法,也可能变为失败状态(rejected)并传递失败信息。

​ 当其中任一种情况出现时,Promise 对象的 then 方法绑定的处理方法(handlers )就会被调用(then方法包含两个参数:onfulfilled 和 onrejected,它们都是 Function 类型。

  1. 当Promise状态为fulfilled时,调用 then 的 onfulfilled 方法
  2. 当Promise状态为rejected时,调用 then 的 onrejected 方法,

所以在异步操作的完成和绑定处理方法之间不存在竞争)

​ 而为什么Promise可以被链式调用主要是因为 Promise.prototype.then和Promise.prototype.catch方法返回promise 对象, 所以它们可以被链式调用

来自MDN
Promise.prototype

Promise对象的属性和方法

  1. Promise对象所具有的属性
    1. Promise.length 构造器参数的数目(其值总是为1)
    2. Promise.prototype Promise构造器的原型
  2. Promise对象所具有的方法
    1. Promise.all 并行运行异步操作
    2. Promise.race 并行运行异步操作
    3. Promise.reject 手动创建一个已经 resolve的Promise 快捷方法
    4. Promise.resolve 手动创建一个已经 reject 的Promise 快捷方法
  3. Promise原型
    1. Promise.prototype.catch 抓取Promise执行过程中出现的异常和reject抛出的异常
    2. Promise.prototype.then 异步操作完成后所要执行的函数
    3. Promise.prototype.finally 无论promise状态最终都会执行的函数

Promise对象的简单用法(基本异步使用)

// 如果异步操作执行成功,则使用resolve来表示promise对象异步操作成功
// 如果异步操作执行成功,则使用reject来表示promise对象异步操作失败
// 其中,resolve和reject其实是一个回调函数,在执行的时候可以携带参数给异步操作执行完成后要处理的函数
var myPromise = new Promise((resovle, reject) => {

    // 在这里我们执行以下异步操作
    // 例如
    // 1. 向后端接口请求数据,同时更新界面
    // 2. 异步加载图片
    // 3. 文件的读写操作
    // 4. 数据库的相关操作
    // 5. 等等
    setTimeout(() => {
        console.log("hello world");
        reject("execute failed!");
    }, 1000);

});


// 异步操作完成后向对应的处理函数
// then(cb)     若异步操作执行成功就会跳入到该函数执行
// catch(cb)    若异步操作执行失败就会跳入到该函数执行 
// finally(cb)  无论异步操作执行成功还是失败都会跳入到该函数执行
myPromise.then((success) => {
    // 处理异步操作成功的函数
    console.log(`success value is ${success}`);
}).catch((err) => {
    // 处理异步操作失败的函数
    console.log(`error value is ${err}`);
}).finally(() => {
    // 无论成功还是失败都会执行的函数
    console.log("finally")
})

一系列异步操作(系列异步操作)

// Promise最强大的地方就是可以进行链式调用,来避免以前遇到的回调地狱问题
// 在执行一系列异步操作时,我们只要在最后.catch一下就可以抓获前面异步操作所可能出现的异常
// 在执行异步操作时,如果后面还要进行下一个异步操作,那么需要在这个异步操作返回一个新的Promise供下面的then函数使用
// 在进行一系列异步操作时,如果其中的一个异步操作出现异常,那么后续的异步操作就不会被执行
new Promise((resovle, reject) => {
    
    // 异步1
    setTimeout(() => {
        console.log("洗菜");
        resovle("洗菜完成");
    }, 1000);

}).then((success) => {

    
    console.log(`success value is ${success}`);
    return new Promise((resovle, reject) => {
        // 异步2
        setTimeout(() => {
            console.log("做饭");
            // resovle("做饭完成");
            reject("做饭失败");
        }, 1000);
    });

}).then((success) => {

    console.log(`success value is ${success}`);  
    return new Promise((resovle, reject) => {
        // 异步3
        setTimeout(() => {
            console.log("吃饭");
            resovle("吃饭成功")
            // reject("吃饭失败");
        }, 1000);
    });


}).then((success) => {

    // 异步操作执行成功
    console.log(`success value is ${success}`);

}).catch((err) => {

    // 异步操作链中出现异常错误
    console.log(`error value is ${err}`);

})

可同时进行的异步操作(组合异步操作)

//在这里共有两组异步操作
// 异步操作1 p1 洗澡
// 异步操作2 p2 洗菜->做饭
var p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log("洗澡", new Date());
        // resolve("洗澡完成");
        reject("洗澡失败");
    }, 1000);
})

var p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log("洗菜", new Date());
        resolve("洗菜完成");
        // reject("洗菜失败");
    }, 1000);
}).then((res) => {
    console.log(res, new Date())
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("做饭", new Date());
            // resolve("做饭完成");
            reject("做饭失败");
        }, 1000);
    })
});

// 通过使用Promise.all来使得异步操作1和异步操作2同时进行
// 然后在then回调函数中同时处理两个异步操作返回回来的结果
// Promise.all在任意一个传入的 promise 失败时返回失败
Promise.all([p1, p2]).then(([r1, r2]) => {
    console.log(r1, r2, new Date());
}).catch((err) => {
    console.log(err.toString());
})



var p4 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log("我快一点");
        resolve("我快一点");
    }, 1000);s
});

var p5 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log("我慢一点");
        reject("我慢一点");
    }, 2000);
});

// 现在有2系列异步操作 p4,p5
// 如果p4异步操作完成的最快,则fastestValue为p1所返回的值,err也同理
// 注意:即使慢一点的异步操作也不会因为快一点的异步操作而中途停止,只是then中回调函数的参数是快一点异步操作的返回值罢了
// 即Promise.race([p4,p5])返回的是执行快一点的Promise对象
Promise.race([p4, p5]).then(fastestValue => {
    console.log(fastestValue);
}).catch((err) => {
    console.log(err.toString());
});

Promise的简单使用就介绍到这里,更加详细的可参考下方的资料

​ 网址1:http://es6.ruanyifeng.com/#docs/promise

​ 网址2:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

最后

这篇文章只是阐述了我对Promise的理解,不足之处,请各位大佬多多指教!

发布了26 篇原创文章 · 获赞 1 · 访问量 1202

猜你喜欢

转载自blog.csdn.net/bleeding_sky/article/details/104223586
今日推荐