js之Promise快速学习/复习

Promise

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。

Promise的功能是将复杂的异步操作轻松的进行模式化

下圖為Promise的運行機制。
在这里插入图片描述

Promise三种状态

在这里插入图片描述

Promise重要特点

  • promise对象的状态有Pending(初始化状态),Fulfilled(成功状态),Rejected(失败状态)
  • 这些状态只受异步操作的影响,外面任何操作都无法手动改变
  • promise对象的状态,从Pending转换为Fulfilled或Rejected之后, 这个promise对象的状态就不会再发生任何变化。

学习Promise的主要目的

  • 避免了回调地狱
  • 提供统一接口(then方法,catch方法),获取异步操作的消息 ,使异步操作规范容易

创建Promise对象

我们先来创建一个Promise对象,可以使用new来调用Promise的构造器来进行实例化:

var promise = new Promise(function(resolve, reject) {
    // 异步操作	
    // 处理结束后、调用resolve 或 reject
    if (...) // 某个异步操作成功
    	resolve(...some value)
    else
    	reject(...some error)
})
  • 结合图与上述代码可以看出,resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果(及上述代码中的some value),作为参数传递出去
  • reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去

resolve()函数

  • resolve函数的参数可以是一个正常的值,也可能还是一个Promise实例
  • 如果resolve函数的参数还是一个Promise实例的话,外层的实例的状态就会传递给内层的实例,
var p1 = new Promise(function(resolve,reject) {
.....
});
var p2 = new Promise(function(resolve,reject) {
.....
resolve(p1);
});
  • 进行resolve函数后,如果后边还有语句,他们仍会执行,并且会首先打印出来(原因参照下面的Promise执行顺序),但是一般来说,resolve函数或reject函数被调用后,Promise的使命就应该完成了,所以我们应该避免在这个位置后边再放代码,最好直接在resolve前加上return

then()方法

then()方法在成功和失败时都可以使用

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)

通过new生成实例后,然后用then方法指定resolvereject状态回调函数:

promise.then(function(value) {
// 成功(resolve)时的操作,可选函数,一般都会写
},function(error) {
// 失败(reject)时的操作,可选函数,可以只保留成功时的操作
})
// 如果只想写失败情况下的操作,可以这样写:promise.then(undefined, onRejected) 
// 不过这种情况下 promise.catch(onRejected) 应该是个更好的选择。

catch()方法

使用catch方法等同于使用then方法的第二个参数

实际上不管是 then 还是 catch 方法调用,都返回了一个新的promise对象

function asyncFunction() {
    
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve('Async Hello world');
        }, 16);
    });
}
asyncFunction()
.then(function (value) { // then()
    console.log(value);    //  'Async Hello world'
})
.catch(function (error) { // catch()
    console.log(error);
});

Promise执行顺序

var promise = new Promise(function (resolve){
    console.log("inner promise"); // 第1步执行
    resolve(42); // 把42传递给then方法
});
promise.then(function(value){
    console.log(value); // 第3步执行
});
console.log("outer promise"); // 第2步执行

// inner promise 
// outer promise 
// 42            

为什么是这样的执行顺序呢?

  • 首先,Promise新建后会立即执行,因此率先consoleinner promise,
  • 然后由于then方法是当Promise状态转化后才执行的,因此在Pomise外部的outer promise显然和 inner promise是同步任务,所以接下来console的就是outer promise这一条,
  • 这时脚本同步任务执行完成了,终于轮到了then方法上场

你可以这样理解:异步操作像是多车道行车,不会阻塞主车道,而同步操作则都是行驶在主车道上的。

Promise().then().then....catch()多任务串行执行

情景化理解: 在一个任务链中,比如我要向上级部门一层层的往上提交申请,if(某种条件)承诺帮你resolve解决问题,else承诺reject你的请求. 他给出的resolve问题的办法只是个空头Promise,then到总经理那实现具体承诺,如果总经理还是给一个空头承诺(返回Promise实例),还得then到董事长那里… 任意一步做出的是reject的承诺,还有什么好说的,被拒绝了,后面的就不会再往上走了呀. 准备catch 拒绝通知吧
所以其实串行是依次执行的意思,前边的任务执行失败了,后续任务就全部堵塞,不再执行下去,只有前边的任务成功执行了,后续任务才有机会继续挨个执行。

// 1. 若有多个异步任务串行执行
job1.then(job2).then(job3).catch(handleError); // job1、job2和job3都是Promise对象

Promise的一些静态方法

  • Promise.all([p1,p2,...])多任务并行执行
    多个任务同时执行,当它们都成功时才进入then,返回结果数组.
  • Promise.race([p1,p2,...])多任务赛跑.
    then()和catch(),谁先调用算谁的,其它任务中断.
// 1. 同时执行p1和p2,并在它们都完成后执行then: // Promise.all
var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
Promise.all([p1, p2]).then(function (results) {
    console.log(results); // 获得一个Array: ['P1', 'P2']
});

// 2. 当多个异步任务是为了容错,优先出来的展示即可时 //  Promise.race
var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
Promise.race([p1, p2]).then(function (result) {
    console.log(result); // 'P1'
});

实际上Promise也是有缺点的,它状态一经改变就凝固不动了,因此也无法被取消,而且如果你忘了为Promise设置回调函数,那你将无法得知Promise进行到哪一步了

发布了46 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/yuanfangyoushan/article/details/100047253