来说一下Promise对象?

69 阅读4分钟

异步编程简介

异步编程历史

前端异步编程经历callback、promise、generate、async/await几个阶段。 目前在简单场景使用回调,步骤比较多的场景使用promise和async/await,generate昙花一现,由于其api不易理解并且不易于使用而很少使用。(Promise A+ 规范【中文版】-icode9专业技术文章分享

异步编程简介

异步编程历史 前端异步编程经历callback、promise、generate、async/await几个阶段。

目前在简单场景使用回调,步骤比较多的场景使用promise和async/await,generate昙花一现,由于其api不易理解并且不易于使用而很少使用。

promise语法

promise对象

new Promise对象时候传入函数,函数立即执行,函数接收resolve、reject参数,调用resolve或reject时候会改变promise状态。状态改变后不会再变化。 promise三种状态
pending
fullfilled
rejected

未调用resolve或者reject时候处于pending状态,调用resolve后处于fullfilled状态,调用reject后处于rejected状态。如果在pending状态时候,执行任务抛出错误,则变成reject状态。
状态变化后,会执行通过then注册的回调。执行顺序和调用then方法的顺序相同。
调用then方法时候,如果状态是pending则注册回调,等到状态改变时候执行,如果状态已经改变则执行相应的回调。

const p = new Promise((resolve, reject) => {
	resolve('test');
});
p.then(
	data => console.log(1, 'resolve', data),
  data => console.log(1, 'reject', data)
);
p.then(
	data => console.log(2, 'resolve', data),
  data => console.log(2, 'reject', data)
);
// 执行结果
1 "resolve" "test"
2 "resolve" "test"
const p = new Promise((resolve, reject) => {
  throw new Error('test-error');
  // 由于抛出错误,promise状态已经改变为rejected,再调用resolve将不会改变promise状态
	resolve('test');
});

p.then(
	data => console.log(1, 'resolve', data),
  data => console.log(1, 'reject', data)
);

p.then(
	data => console.log(2, 'resolve', data),
  data => console.log(2, 'reject', data)
);

// 执行结果
1 "reject" Error: test-error
2 "reject" Error: test-error
const p = new Promise((resolve, reject) => {
	setTimeout(() => {
  	resolve('test');
  }, 1000);
});

p.then(
	data => console.log(1, 'resolve', data),
  data => console.log(1, 'reject', data)
);

// 执行结果
1s后打印 `1 "resolve" "test"`

promise对象的方法:then、catch、all、race

then

then方法接受两个参数,onFulfilled(状态变为fullfilled的回调)和onRejected(状态变为rejected的回调)。返回一个新的promise对象,返回的promise对象的状态与then的参数(onFulfilled、onRejected)和onFulfilled、onRejected方法中返回的值有关

1. then方法不传参数

如果不传参数,则then方法返回的promise和调用then的promise的状态一致。 更具体地,如果没有onFullfilled参数并且promise的状态为fullfilled,那么then方法返回的promise和调用then方法的promise状态一致;如果没有onRejected参数并且promise状态为rejected,那么then方法返回的promise和调用then方法的promise状态一致。

可以简单地理解:如果上一个promise不处理,那就下一个promise处理。

var p = new Promise(resolve => {
    throw new Error('test');
});

p
.then(
    () => {}
)
.then(
    data => console.log('resolve', data),
    err => console.log('reject', err)
    
);

// 执行结果
reject Error: test
var p = new Promise(resolve => {
    resolve('test');
});

p
.then(
    undefined, () => {}
)
.then(
    data => console.log('resolve', data),
    err => console.log('reject', err)
    
);

// 执行结果
resolve test

catch方法

catch方法和then方法的reject回调用法相同,如果这时候任务处于rejected状态,则直接执行catch,catch的参数就是reject的reason;如果任务处于pending状态,则注册catch回调,等到状态变成rejected时候再执行

p.then((val) => console.log('fulfilled:', val))
  .catch((err) => console.log('rejected', err));

// 等同于
p.then((val) => console.log('fulfilled:', val))
 .then(null, (err) => console.log("rejected:", err));

all

Promise.all方法用于多个异步任务执行,当所有任务都正常完成时候,再做后面处理的场景。 Promise.all方法接收一个promise数组作为参数,返回一个promise,当参数的数组中的所有promise都resolve时候,返回的promise才会resolve;而若有一个参数的数组中的promise reject,返回的promise就会reject。 Promise.all方法返回的promise的then的第一个参数onFullfilled回调的参数也是一个数组,对应参数中的数组promise resolve的结果。

const p1 = Promise.resolve(1);
const p2 = new Promise(resolve => {
	setTimeout(() => {
  	resolve(2);
  }, 1000);
});

Promise.all([p1, p2])
.then(
	([result1, result2]) => {console.log('resolve', result1, result2);}
);

// 执行结果
resolve 1 2
const p1 = Promise.reject(1);
const p2 = new Promise(resolve => {
	setTimeout(() => {
  	resolve(2);
  }, 1000);
});
Promise.all([p1, p2])
.then(
	([result1, result2]) => {console.log('resolve', result1, result2);},
    e => console.log('reject', e)
);
// 执行结果
reject 1

race

Promise.race方法用于多个异步任务执行,当有其中一个任务完成或失败时候,就执行后续处理的场景。 Promise.race接收一个promise数组作为参数,返回一个新的promise。当参数数组中其中一个promise resolve或者reject,返回的promise就相应地改变状态。

var p1 = Promise.reject(1);
var p2 = new Promise(resolve => {
	setTimeout(() => {
  	resolve(2);
  }, 1000);
});

Promise.race([p1, p2])
.then(
		data => {console.log('resolve', data);},
    e => {console.log('reject', e);}
);

// 执行结果
reject 1