Promise介绍

Promise

含义
  • Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
  • 从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
  • Promise 对象代表异步操作 => 其中有三种状态:
    pending(进行中)fulfilled(已成功)rejected(已失败)
  • Promise状态改变的过程:从pending变为fulfilled 和从 pending变为rejected,一旦状态确定为其中的一种,那么就不会再发生改变。
  • Promise 的缺点:一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

基本用法
  • Promise对象是一个构造函数,用来生成Promise实例
var promise1 = new Promise(function(resolve, reject){
    let index = 0;
    index++;
    if (index <= 2)
        resolve('Jack')
    throw new Error('Not function!')
})
.then(data => console.log(data))
.catch(err => console.log(err))
 
// 理解一下上面的代码:首先我们应用Promise对象进行实例化,promise1是
// Promise的实例化对象。Promise里面接受一个函数作为参数 => 
// 在函数内:判断 index 的值是否 <=2,成功执行 resolve函数,否则抛出错误
// 内部抛出错误将会被 catch 捕捉,最后打印
// 下面会详细介绍 then 和 catch
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是 resolvereject
resolve函数的作用是,将Promise对象的状态从 “未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去

reject函数的作用是,将Promise对象的状态从 “未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
  • Promise实例生成以后,可以用then方法分别指定 resolved状态rejected状态的回调函数。(如上述代码)

注意①:

let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi!');

// Promise
// Hi!
// resolved
  • Promise 新建后立即执行,所以首先输出的是Promise。然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出。


    注意②
  • 注意,调用 resolvereject并不会终结 Promise 的参数函数的执行。
new Promise((resolve, reject) => {
  resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});
// 2
// 1
// 在控制台打印的语句依然可以执行,所以为了不必要的麻烦,我们通常
// 采用下面这一种写法。

new Promise((resolve, reject) => {
  return resolve(1);
  // 后面的语句不会执行
  console.log(2);
})

Promise.prototype.then()
  • Promise 实例具有 then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。
  • then方法返回的是一个新的Promise实例
// promise1为 Promise 的实例
promise1.then(function(data) {
  return data;
}).then(function(post) {
	return post+1;  // 相当于 data + 1
});
// 上面的代码使用then方法,依次指定了两个回调函数。第一个回调函数完成以
// 后,会将返回结果作为参数,传入第二个回调函数。
  • 这时,前一个回调函数,有可能返回的还是一个Promise对象(即有异步操作),这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。
promise1.then(function(data) {
  return new Promise(function(resolve, reject){})
}).then(function(){}, function(){});

// 如果状态为 resolve,那么执行then里面的第一个函数,否则执行第二个
// 补充:then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)
// 是rejected状态的回调函数。
// 下面会介绍捕获内部错误的 catch 方法

Promise.prototype.catch()
  • Promise.prototype.catch方法是 .then(null, rejection).then(undefined, rejection) 的别名,用于指定发生错误时的回调函数。
let promise = new Promise(function(resolve, reject){})

promise.then(function(){})
	   .catch(function(){})
// promise 为 Promise的实例。
//如果该对象状态变为resolved,则会调用then方法指定的回调函数;如果异步操作 
//抛出错误,状态就会变为rejected,就会调用catch方法指定的回调函数,处理这
//个错误。 

//另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。

再次引用上面举过的例子:

var promise = new Promise(function(resolve, reject){
    let index = 0;
    index++;
    if (index <= 2)
        resolve('Jack')
    throw new Error('Not function!')
})
.then(data => console.log(data))
.catch(err => console.log(err)) // 'Not function!'

// 我们主动抛出的错误会被 catch捕获到,然后再控制台打印
// 假如 状态已经由 pending => resolve, 那么再次抛出错误就无效了
  • 一般总是建议,Promise 对象后面要跟catch方法,这样可以处理 Promise 内部发生的错误。catch方法返回的还是一个 Promise 对象,因此后面还可以接着调用then方法。
const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
  });
};
someAsyncThing()
.catch(function(error) {})
.then(function() {});

// 如果实例不发生错误的话,会继续执行 .then后面的内容,否则会提前被 catch
// 捕获到,这样提高了排错的效率。
  • catch 内部还能抛出错误,给下一个 catch 捕获到。
const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
  });
};

someAsyncThing()
.catch(function(error) {
	throw new Error('ExistedProblem')
}).catch(function(){})

// 后面的 catch 会捕获到前一个 catch 抛出错误进而进行处理。

Promise.prototype.finally()
  • finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
// promise 是 Promise 的实例
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

// 此时不管 promise 的状态变为 resolve执行.then或者 状态变为 reject执行
// catch, finally 都会执行
  • 从上面的代码可知, finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。
// resolve 的值是 undefined
Promise.resolve(2).then(() => {}, () => {})

// resolve 的值是 2
Promise.resolve(2).finally(() => {})

// reject 的值是 undefined
Promise.reject(3).then(() => {}, () => {})

// reject 的值是 3
Promise.reject(3).finally(() => {})
  • 从上面的代码可知,finally方法总是会返回原来的值。

Promise.all()
  • Promise.all() 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
// 其中 promise 和 promise_1 均为 Promise 实例
var promise_2 = Promise.all([promise, promise_1])
Promise.all() 方法可以接受一个数组作为参数,也可接受具有 Iterator 接口且返回的每个成员均为 Promise 实例

(1)只有 promise, promise_1 的状态都变成 fulfilledpromise_2的状态才会变成fulfilled,此时 promise, promise_1 返回值组成一个数组,传递给p的回调函数。

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

注意:如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。

var promise = new Promise(function(resolve, reject){
    let index = 4;
    index++;
    if (index <= 2)
        resolve('Jack')
    throw new Error('Not function!')
})
.then(data => console.log(data))
.catch(err => console.log(err))    // 最后执行的是这个

var promise_1 = new Promise(function(resolve, reject){
    return resolve('summary')
})

var promise_2 = Promise.all([promise, promise_1])

promise_2.then(function(){console.log('yes')})
         .catch(function(){err => console.log(err)}) // 最后是不会执行的
//       .catch(function(){console.log('失败了')})  => 例外:会执行

console.log(promise_2)     // resolved

// 其实不执行指的是 Promise 实例不会传递错误指数给 catch,所以参数 err
// 等于 undefined, 所以最后才会没有结果,但是捕获还是照样进行的。

// 当promise的catch 执行完后,他返回一个新的Promise对象,这个对象的状态为 // resolve, 与 promise_1合起来,所以promise_2的状态为 resolved

// 这段代码其实本质就是判断 index是否小于等于2,大家也可以把 promise_1的
// catch删去看下最后控制台打印是否是 promise_2的 catch()

Promise.race()
// 其中 promise 和 promise_1 均为 Promise 实例
var promise_2 = Promise.race([promise, promise_1])
Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
只要 promise、promise_1 之中有一个实例率先改变状态,p的状态就跟着改变。那个 率先改变的 Promise 实例的返回值,就传递给p的回调函数。
var promise = new Promise(function(resolve, reject){
    let index = 4;
    index++;
    if (index <= 2)
        resolve('Jack')
    throw new Error('Not function!')
})
.then(data => console.log(data))
.catch(err => console.log(err))   

var promise_1 = new Promise(function(resolve, reject){
    return resolve('summary')
})

var promise_2 = Promise.race([promise, promise_1])

promise_2.then(function(){console.log('yes')})
         .catch(function(){err => console.log(err)}) 

console.log(promise_2)     // rejected
// 结果上面 all()方法一样,最后输出的是 promise抛出的错误
// 但是不同的是,此时的 promise_2状态为 reject
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值