继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

JavaScript异步编程之Promise

为爱心太软
关注TA
已关注
手记 151
粉丝 1.4万
获赞 860

基本概念

Promise 是一个对象,从它可以获取异步操作的消息。
Promise 不需要去订阅一个事件,也不需要传递一个回调函数,而是通过自身状态的改变来通知目标函数。

Promise 对象的状态有以下三个特点:

1、Promise 对象有三种状态:pending(进行中)、resolved(已成功)和rejected(已失败)。
2、Promise 对象的状态改变只有两种可能:从 pending 变为 resolved 和从 pending 变为 rejected。
3、只有当 Promise 对象的状态改变时,才能通过 then() 方法采取特定的行动。

例子:

const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        //1秒钟之后:状态从 pending 变为 resolved 
        resolve("ok");
    }, 1000)

});
//状态改变,then()方法的回调函数加入队列中等待执行
//参数(data)的值为 resolve 方法的参数,可任意类型
promise.then((data) => {
    console.log(data);
});
//输出:ok

基本用法

Promise 是一个构造函数,使用 new 来生成 Promise 实例对象。
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject :resolve 函数的作用是,将 Promise 对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在操作成功时调用;reject 函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在操作失败时调用。
Promise 实例对象生成以后,可以用 then() 方法分别指定 resolved 状态和 rejected 状态的回调函数。

例子:

let n = Math.floor(Math.random() * 10 + 1);
const promise = new Promise((resolve, reject) => {
    if (n % 2 === 0) {
        //如果数值为偶数,则变为成功状态
        resolve("偶数");
        console.log(n);
    } else {
        //如果数值为奇数,则变为失败状态
        reject("奇数");
        console.log(n);
    }
});
promise.then(
    //成功状态下的处理函数
    data => {
        console.log(data);
    },
    //失败状态下的处理函数
    data => {
        console.log(data);
    });

通过上面的例子可以发现:

1、then() 方法可以接受两个回调函数作为参数。第一个回调函数是 Promise 对象的状态变为 resolved 时调用,第二个回调函数是 Promise 对象的状态变为 rejected 时调用。其中,第二个函数是可选的,不一定要提供。

例子:

const promise = new Promise((resolve) => {
    resolve("ok");
});
promise.then(
    data => {
        console.log(data);
    });
//输出:ok

也可以使用 then(null, rejection) 的形式只去指定状态为 rejected 时的回调函数。

例子:

const promise = new Promise((resolve, reject) => {
    reject("no");
})
promise.then(
    null,
    (data) => {
        console.log(data);
    });
//输出:no

2、如果调用 resolve 函数和 reject 函数时带有参数,那么它们的参数会被传递给回调函数。
3、调用 resolve 或 reject 并不会终结 Promise 的执行。

Promise 对象的方法

Promise.prototype.then() 方法

then() 的基本用法上面已经介绍过,then() 方法还有一个特点:该方法可以采用链式写法,即 then() 方法后面再调用另一个 then() 方法。

例子:

const promise = new Promise((resolve, reject) => {
    resolve(1);
})
promise.then((data) => {
    console.log(data);
    //返回的数据会作为后一个 then()方法的参数
    return data + 1;
}).then((data) => {
    console.log(data);
    return data + 1;
}).then((data) => {
    console.log(data);
});
//输出:1 2 3

如果前一个 then() 方法返回的还是一个Promise对象,这时后一个then() 方法,就会等待该 Promise 对象的状态发生变化,才会被调用。

例子:

let p1 = () => {
    return new Promise((resolve, reject) => {
        resolve(1);
    });
};
let p2 = (time) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2);
        }, time)
    })
};
p1().then((data) => {
    console.log(data);
    return p2(2000);
}).then((data) => {
    console.log(data);
});
//输出:1 2

Promise.prototype.catch() 方法
Promise.prototype.finally() 方法

catch() 方法是 then(null, rejection) 的别名,用于指定发生错误时的回调函数。
finally() 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。

例子:

let n = Math.floor(Math.random() * 5 + 0);
let arr = [1, "A", "B", 2, 3];
console.log(arr[n]);
const promise = new Promise((resolve, reject) => {
    if (typeof(arr[n]) === "number") {
        setTimeout(() => {
            resolve("数值");
        }, 3000)
    } else {
        setTimeout(() => {
            reject("文本");
        }, 3000)
    }
})
promise.then(
    data => {
        console.log(data);
    }).catch(
    data => {
        console.log(data);
    }).finally(
    () => {
        console.log("end");
    });

Promise.all() 方法

Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。Promise.all() 方法接受一个数组(类数组也可以)作为参数,参数都是 Promise 实例。

下面例子中的 Promise 对象的状态由p1、p2决定,分成两种情况:

1、只有p1、p2的状态都变成 resolved,p 的状态才会变成 resolved,此时p1、p2的返回值组成一个数组,传递给p 的回调函数。

例子:

const p1 = new Promise((resolve, reject) => {
    resolve(1);
});
const p2 = new Promise((resolve, reject) => {
    resolve(2);
});
const p = Promise.all([p1, p2]);
p.then((data) => {
    console.log(data);
}).catch((data) => {
    console.log(data);
});
//输出:[1, 2]

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

例子:

const p1 = new Promise((resolve, reject) => {
    resolve(1);
});
const p2 = new Promise((resolve, reject) => {
    reject(2);
});
const p = Promise.all([p1, p2]);
p.then((data) => {
    console.log(data);
}).catch((data) => {
    console.log(data);
});
//输出:2

Promise.race()方法

Promise.race() 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

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

例子:

let p1 = time => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1);
        }, time);
    })
};
let p2 = time => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(2);
        }, time);
    })
};
const p = Promise.race([p1(100), p2(200)]);
p.then(data => {
    console.log(data);
}).catch((data) => {
    console.log(data);
});
//输出:1

Promise.resolve() 方法
Promise.reject() 方法

Promise.resolve() 方法将现有对象转为 Promise 对象,状态为 resolved。
Promise.reject() 方法将现有对象转为 Promise 对象,状态为 rejected。

例子:

Promise.resolve().then(() => console.log("ok")); //输出:ok
Promise.reject().catch(() => console.log("no")); //输出:no
Promise.resolve("ok").then(data => console.log(data)); //输出:ok
Promise.reject("no").catch(data => console.log(data)); //输出:no

如有错误,欢迎指正,本人不胜感激。

打开App,阅读手记
2人推荐
发表评论
随时随地看视频慕课网APP