什么是promise
ES6异步编程的一种解决方案,将异步操作以同步的方式表达出来,避免层层嵌套的回调函数
为什么要用promise
- 指定回调函数的方式更加灵活
- 使用纯回调函数方式,必须在异步任务执行前指定回调函数
// 成功的回调函数
function successCallback(result) {
console.log("音频文件创建成功: " + result);
}
// 失败的回调函数
function failureCallback(error) {
console.log("音频文件创建失败: " + error);
}
createAudioFileAsync(audioSettings, successCallback, failureCallback)
- promise 可以在启动异步任务后指定回调函数,甚至可以在异步任务结束后绑定回调函数
const promise = createAudioFileAsync(audioSettings);
promise.then(successCallback, failureCallback);
setTimeout(() => {
promise.then(successCallback, failureCallback);
},2000)
- 支持链式调用,解决回调地狱
回调地狱:回调函数嵌套调用,外部回调函数异步执行的结果,是嵌套的回调函数执行的条件
嵌套的回调函数不便于阅读、不便于异常处理
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
Promise 链式调用
doSomething().then(function(result) {
return doSomethingElse(result);
})
.then(function(newResult) {
return doThirdThing(newResult);
})
.then(function(finalResult) {
console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
promise链式调用异常传递
new Promise((resolve,reject) => {
reject(1)
}).then(
value => {
console.log('onResolved',value)
return 2
},
// error => { throw error }
// error => Promise.reject(error)
).then(
value => {
console.log('onResolved',value)
return 3
},
// error => { throw error }
).catch(reason => {
console.log('onRejected',reason)
})
输出:onReject 1
一遇到异常抛出,浏览器就会顺着 Promise 链寻找下一个 onRejected 失败回调函数或者由 .catch() 指定的回调函数,相当于注释代码的两种写法之一
中断promise链
new Promise((resolve, reject) => {
reject(1);
})
.then(() => {
console.log(2);
})
.catch(() => {
console.log(3);
//要中断catch()后面的then()方法,
return new Promise(() => {}); //返回一个padding的promise
})
.then(() => {
console.log(3);
});
promise的特点
对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、resolved(已成功)和rejected(已失败)
一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为resolved和从pending变为rejected
promise内部发生错误,不会影响到外部程序的执行。
无法取消Promise。一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
用法
创造promise 实例时,必须传入一个函数作为参数
new promise(() => {});
该函数可以接收另外两个由JavaScript引擎提供的函数,resolve和reject。函数作用:
- resolve——将Promise对象的状态从pending变为resolved,将异步操作的结果,作为参数传递出去
- reject——将Promise对象的状态从pending变为rejected,将异步操作报出的错误,作为参数传递出去
let promise = new promise((resolve, reject) => {
//do something
if(true){
//将参数返回,供then方法使用
resolve('value');
}else {
reject('error');
}
});
promise 实例方法
promise.prototype.then()
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
then方法返回的是一个新的Promise实例
promise.then(
//resolved时调用,value为resolve函数返回的参数
value => {
console.log(value);
},
err => {
//reject时调用
console.log(err);
}
);
当then方法只有一个函数参数时,此时为resolved状态的回调方法
promise .then(value => {
console.log(value);
})
.catch(err => {
//
}
`推荐这种方式,可以捕获前面then方法执行中的错误
Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名
Promise 新建后就会立即执行,并且调用resolve或reject后不会终结 Promise的参数函数的执行。
let promise = new Promise(function(resolve){
console.log('promise');
resolve();
console.log(1)
})
promise.then(function() {
console.log('resolved');
})
console.log(2)
//promise
//1
//2
//resolved
Promise.then()返回的promise状态是什么?
由then()指定的回调函数的执行结果决定
1、如果抛出异常,返回的promise变为rejected,error为抛出的异常
2、如果返回非promise的任意值,返回的promise变为resolved状态,value为返回的值
3、如果返回另一个新的promise,此promise的结果就是返回的promise的结果
const p = new Promise(function(resolve,rejected){
resolve(1)
})
p.then(value => {
//情况1:抛出异常
throw '错误'
//2.返回一个值
return value+1;
//3.返回一个Promise
return new Promise((resolve, reject) => {
resolve(value+2)
});
return new Promise((resolve, reject) => {
reject(value+3)
});
//4.没有返回值
相当于 return undefined
}).then(value => {
console.log('onResolved',value);
},error => {
console.log('onRejected',error)
});
- 抛出的异常将作为then方法返回的promise的reject的值传递出
输出: onRejected 错误
- return的值将作为then方法返回的promise的resolve的值传递出
输出: onResolved 2
- return 的promise的结果将作为then方法返回的promise的结果
分别输出: onResolved 3 ,onRejected 4
- 构造then方法的函数没有向then方法返回的promise对象的resolve方法传递值。因此resolve返回的是undefined
输出: onResolved undefined
- promise.catch()
- promise.finally() 无论成功失败都执行
静态api方法
promise.all() 将多个 Promise 实例,包装成一个新的 Promise 实例
const p =Promise.all([p1, p2, p3]);
p1,p2,p3都是Promise实例;p的状态由p1、p2、p3决定,分成两种情况。
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
promise.race()方法是将多个Promise实例包装为一个实例
const p = Promise.race([p1, p2, p3]);
上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
Promise.resolve()
Promise.resolve(1)
// 等价于
new Promise(resolve => resolve(1))
Promise.resolve()方法的参数:
- 参数是promise实例
返回这个实例 - 参数是一个thenable对象
thenable对象指的是具有then方法的对象
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function (value) {
console.log(value); // 42
});
Promise.resolve()方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then()方法。
- 参数不是具有then()方法的对象,或根本就不是对象
如果参数是一个原始值,或者是一个不具有then()方法的对象,则Promise.resolve()方法返回一个新的 Promise 对象,状态为resolved。
const p = Promise.resolve('Hello');
p.then(function (s) {
console.log(s)
});
//hello
- 不带任何参数
直接返回一个resolved状态的 Promise 对象。