Promise 对象promise
是 JavaScript 的异步操做解决方案,为异步操做提供统一接口。app
目前 JavaScript 原生支持 Promise 对象异步
它起到代理做用(proxy),充当异步操做与回调函数之间的中介,使得异步操做具有同步操做的接口。函数
Promise 可让异步操做写起来,就像在写同步操做的流程,而没必要一层层地嵌套回调函数。spa
function f1(resolve, reject) { // 异步代码... } var p1 = new Promise(f1);
// 构造函数接受一个回调函数 做为参数,里面是异步操做的代码。而后,返回的就是一个 Promise 实例Promisef1()f1()p1
var p1 = new Promise(f1); p1.then(f2);
f1() 的异步操做执行完成,就会执行 f2()
prototype
// 传统写法 step1(function (value1) { step2(value1, function(value2) { step3(value2, function(value3) { step4(value3, function(value4) { // ... }); }); }); }); // Promise 的写法 (new Promise(step1)).then(step2).then(step3).then(step4);
var promise = new Promise(function (resolve, reject) { // ... if (/* 异步操做成功 */){ resolve(value); } else { /* 异步操做失败 */ reject(new Error()); } });
// 该函数的两个参数分别是 和 。它们是两个函数,由 JavaScript 引擎提供,不用本身实现resolvereject
resolve() 函数设计
做用是,将Promise实例的状态从“未完成”变为“成功”(即从pending变为fulfilled)代理
在异步操做成功时调用,并将异步操做的结果,做为参数传递出去。code
reject函数对象
做用是,将Promise实例的状态从“未完成”变为“失败”(即从pending变为rejected)
在异步操做失败时调用,并将异步操做报出的错误,做为参数传递出去。
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(resolve, ms, 'done'); }); } timeout(100)
上面代码中,timeout(100) 返回一个 Promise 实例。100毫秒之后,该实例的状态会变为 fulfilled
var p1 = new Promise(function (resolve, reject) { resolve('成功'); }); p1.then(console.log, console.error); // "成功" var p2 = new Promise(function (resolve, reject) { reject(new Error('失败')); }); p2.then(console.log, console.error); // Error: 失败
p1 和 p2 都是Promise 实例,它们的 then() 方法绑定两个回调函数:成功时的回调函数 console.log,失败时的回调函数 console.error(能够省略)。
p1 的状态变为成功,p2 的状态变为失败
对应的回调函数会收到异步操做传回的值,而后在控制台输出
var preloadImage = function (path) { return new Promise(function (resolve, reject) { var image = new Image(); image.onload = resolve; image.onerror = reject; image.src = path; }); };
调用
preloadImage('https://example.com/my.jpg') .then(function (e) { document.body.append(e.target) }) .then(function () { console.log('加载成功') })
new Promise(function (resolve, reject) { resolve(1); }).then(console.log); console.log(2); // 2 // 1
// 上面代码会先输出 2,再输出 1 。
// 由于 console.log(2)是同步任务,而 then 的回调函数属于异步任务,必定晚于同步任务执行
setTimeout(function() { console.log(1); }, 0); new Promise(function (resolve, reject) { resolve(2); }).then(console.log); console.log(3); // 3 // 2 // 1
输出结果是321。这说明 then 的回调函数的执行时间,早于setTimeout(fn, 0)。
由于 then 是本轮事件循环执行,setTimeout(fn, 0)在下一轮事件循环开始时执行