Promise本意“承诺”,是一个“承诺将来会执行”的对象
基本用法是reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch ,resolve的东西,一定会进入then的第一个回调,肯定不会进入catch, 网络异常(比如断网),会直接进入catch而不会进入then的第二个回调
let p = new Promise(function(resolve,reject){
console.log('立即执行');
setTimeout(function(){
resolve('成功');
},100);
});
p.then(function(data){
console.log(data);
},function(err){
console.log(err);
})
创建Promise对象时,executor执行器会同步执行(在Promise构造函数返回Promise对象之前就会被执行),executor是一个函数,函数内部通常调用用来执行一些异步操作,操作完成后,调用resolve触发promise的成功状态,或者调用reject触发promise的失败状态。
then 用来注册Promise状态确定后的回调;then的参数有:处理成功返回结果的函数,处理错误结果的函数;then方法返回一个Promise,因此可以继续调用then,即实例化后的Promise对象可以进行链式调用
//读取文件1.txt ,1.txt中存放着文本2.txt,再读取2.txt文件的内容
let fs = require('fs');
function read(path){
return new Promise(function(resolve,reject){
fs.readFile(path,'utf8',function(err,data){
if(err){
reject(err);
}
resolve(data)
})
})
}
read('1.txt').then(data=>{
console.log(data);
//return data;// 如果返回了一个普通值,会将这个值作为下一次then的成功会回调
return read(data);
},err=>{
console.log(err);
}).then(data=>{
console.log('next then :',data);
},err=>{
console.log(err);
})
Promise状态
1、pending:默认状态,就是初始化Promise时,调用executor执行器函数后的状态。
2、fulfilled:完成状态/成功状态,异步操作调用resolve()后的状态
3、rejected:失败状态,异步操作调用reject()后的状态
状态转化:pending ->fulfilled ,pending ->rejected 这个状态转化是单向的,不可逆转的,也就是一旦进入成功就成功了,一旦进入失败就失败了
链式调用返回一个Promise,该Promise的状态主要根据第一个then方法返回的值确定
1、如果第一个then()方法中返回了一个参数值,那么返回的Promise将会变成接收状态。
2、如果第一个then()方法中抛出了一个异常,那么返回的Promise将会变成拒绝状态。
3、如果第一个then()方法调用resolve()方法,那么返回的Promise将会变成接收状态。
4、如果第一个then()方法调用reject()方法,那么返回的Promise将会变成拒绝状态。
5、如果第一个then()方法返回了一个未知状态(pending)的Promise新实例,那么返回的新 Promise就是未知状态。
不管第一个then走的成功还是失败,都会将返回值(没有返回值,就返回undefined)作为下一个then的结果
Promise.all(promises)
all 接收一个参数,它必须是可以迭代的,比如数组,它通常用来处理一些并发的异步操作, 是多个promise对象的结果集合
//Promise.all方法执行后返回的依旧是promise
//它是并发执行的,返回结果按照执行顺序,即ele2是read('2.txt')的返回结果
//all里面的都执行成功了,才表示成功,有一个失败了,就失败
Promise.all([read('1.txt'),read('2.txt')]).then(([ele1,ele2])=>{
console.log(ele1,ele2);
},err=>{
console.log(err);
});
Promise.race()
Promise.race() 和all基本相同,race“赛跑”的意思,race的状态变化不是全部受参数内的状态影响,一旦参数内有一个值的状态发生的改变,那么该Promise的状态就是改变的状态
// race如果先成功了那就成功了如果先失败了那就失败了
Promise.race([read('1.txt'),read('2.txt')]).then(([ele1,ele2])=>{
console.log(ele1,ele2);
},err=>{
console.log(err);
});
Promise.resolve() / Promise.reject()
参数可以是普通值或Promise对象
let p = Promise.resolve([1,2]);
p.then(data=>{
console.log(data);
})
Promise.reject([1,2,3]).then(null,function(err){
console.log('err',err)
});
let p2 = Promise.reject(['fail']);
let p3 = Promise.resolve(p2).then(data=>{
console.log('不执行');
},err=>{
console.log('resolve接收rejected状态的promise',err);
});
组合 promise
例如,假设我们需要编程解决如下需求:
- 创建 HTTP 请求,等待请求结束并打印出结果;
- 再创建两个并行 HTTP 请求;
- 等这两个请求结束后,打印出它们的结果
// 第一次调用
const call1Promise = rp('http://example.com/');
call1Promise.then(result1 => {
// 第一个请求完成后会执行
console.log(result1);
const call2Promise = rp('http://example.com/');
const call3Promise = rp('http://example.com/');
return Promise.all([call2Promise, call3Promise]);
}).then(arr => {
// 两个 promise 都结束后会执行
console.log(arr[0]);
console.log(arr[1]);
})
我们开头创建了第一个 HTTP 请求,并且加了个完成时候运行的回调。在这个回调函数里,我们为随后的 HTTP 请求创建了另外两个 promise。这两个 promise 同时执行,我们需要加一个能等它们都完成后才执行的回调函数。因此,我们需要用 Promise.all 将它们组合到同一个 promise 中,它们都结束后这个 promise 才算完成。这个回调返回的是 promise 对象,所以我们要再加一个 then 回调函数来打印结果。
如果我们必须执行更多异步操作,或者加上错误处理,这种方法最后很容易产生一堆乱七八糟的 then, Promise.all 和回调函数。JavaScript ES7 中的 async / await 让多个异步 promise 协同工作起来更容易。
Async 方法
Async 是定义返回 promise 对象函数的快捷方法。
function f() {
return Promise.resolve('TEST');
}
// asyncF 和 f 是等价的
async function asyncF() {
return 'TEST';
}
Await
每个 async 方法都返回一个 promise 对象。因此,JavaScript 解释器就明白所有 async 方法中的操作都被封装在 promise 里异步执行。所以解释器能够允许它们等待其他 promise 执行完。
await 只能被用在 async 方法中,让我们能同步等待 promise 执行完。如果在 async 函数外使用 promise, 我们仍然需要用 then 回调函数。
解决上面提到的多个异步 promise 协同工作:
// 将解决方法封装到 async 函数中
async function solution() {
// 等待第一个 HTTP 请求并打印出结果
console.log(await rp('http://example.com/'));
// 创建两个 HTTP 请求,不等它们执行完 —— 让他们同时执行
const call2Promise = rp('http://example.com/'); // Does not wait!
const call3Promise = rp('http://example.com/'); // Does not wait!
// 创建完以后 —— 等待它们都执行完
const response2 = await call2Promise;
const response3 = await call3Promise;
console.log(response2);
console.log(response3);
}
// 调用这一 async 函数
solution().then(() => console.log('Finished'));
实际上,async / await 在底层转换成了 promise 和 then 回调函数。也就是说,这是使用 promise 的语法糖。每次我们使用 await, 解释器都创建一个 promise 对象,然后把剩下的 async 函数中的操作放到 then 回调函数中。
async function f() {
console.log('Starting F');
const result = await rp('http://example.com/');
console.log(result);
}