1.promise初体验

1. Promise是什么

1.1 理解Promise

  • 抽象表达:Promise是JS中进行异步编程的新的解决方案(旧方案是单纯使用回调函数)
    ----异步编程:①fs文件操作 ②数据库操作 ③Ajax ④定时器

  • 具体表达:
    ①从语法上看:Promise是一个构造函数 (自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法)
    ②从功能上看:promise对象用来封装一个异步操作并可以获取其成功/失败的结果值

1.2 Promise的含义

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

1.3 Promise的状态

(1)Promise对象代表一个异步操作,有三种状态:pending(进行中)、 resolved/fulfilled(已成功)、rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected

注意

  • 对象的状态不受外界影响
  • 只有这两种,且一个 promise 对象只能改变一次
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果
  • 无论成功还是失败,都会有一个结果数据。成功的结果数据一般称为 value,而失败的一般称为 reason

1.4 Promise对象的值

实例对象promise的另一个值 PromiseResult
保存着对象 成功/失败 的值(value/reason

resolve/reject可以修改值

1.5 Promise的基本流程

2. Promise的使用

2.1 Promise的基本使用

Promise是一个构造函数,我们可以用new关键字生成一个promise实例来使用

let promise = new Promise((resolve, reject) => {
        //做一些异步操作
        setTimeout(() => {
            console.log('success')
            resolve('promise is success')
        }, 2000)
    })

Promise构造函数接受一个函数作为参数,在这个函数内执行一些异步操作

这个函数拥有两个参数:resolve和reject,这两个都是函数,js引擎会帮你传入

在函数内部调用他们的时候分别代表对外声明异步操作已经成功(resolve)或失败(reject)

为什么会设计的这样复杂?

setTimeout(() => {
  return 1
}, 2000)

这是一个简单的回调方式处理异步操作的结果,但是回调函数被外层的定时器包裹

我们没法简单的拿到回调函数的返回值,这也是回调函数最大的缺陷

所以promise通过resolve和reject方法,对外传递一个可以轻易访问到信息

如果我们需要拿到并处理promise内部resolve的信息,需要使用then方法:

let promise = new Promise((resolve, reject) => {
        //做一些异步操作
        setTimeout(() => {
            console.log('success')
            resolve('promise is success')
        }, 2000)
    })

promise.then(value =>{
	console.log(value)
},reason=>{
	console.log(reason)
})
// promise is success

promise实例上的then方法是promise里最常用的方法,它接受的第一个参数就是promise中resolve出来的值,第二个参数就是reject出来的值,从而我们可以在这个函数内部获取和使用这个值

另一个常用方法是catch,如果这个promise异步操作出了问题

我们会在函数内部调用reject方法传递出去错误信息,代表promise出错了

这时候应该使用catch方法来处理错误信息:

let promise = new Promise((resolve, reject) => {
    //做一些异步操作
    setTimeout(() => {
        console.log('error')
        reject('promise is error')
    }, 2000)
})
promise.then(value => console.log(value))
// 报错 Uncaught (in promise) promise is success
promise.catch(reason => console.log(reason))
// 不报错 输出 promise is error

catch方法只是then的一个别名,不过为了代码清晰易读
我们最好都是用catch,而不是给then传入两个参数,即用then方法处理执行成功的promise,用catch方法处理出错的promise

2.2 为什么要使用Promise

1. 指定回调函数的方式更加灵活

以前:必须再启动异步任务前指定

// 1. 纯回调的形式
// 成功的回调函数
function successCallback(result) {
  console.log("声音文件创建成功:" + result);
}
// 失败的回调函数
function failureCallback(error) {
  console.log("声音文件创建失败:" + error);
}
// 必须先指定回调函数,再执行异步任务
createAudioFileAsync(audioSettings, successCallback, failureCallback) // 回调函数在执行异步任务(函数)前就要指定

promise:启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定)

// 2. 使用Promise
const promise = createAudioFileAsync(audioSettings);  // 执行2秒
setTimeout(() => {
  promise.then(successCallback, failureCallback) // 也可以获取
}, 3000);

2.支持链式调用,可以解决回调地狱问题

什么是回调地狱?

回调函数嵌套调用,外部回调函数异步执行的结果是其内部嵌套的回调函数执行的条件

doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result:' + finalResult)
    }, failureCallback)
  }, failureCallback)
}, failureCallback)

回调地狱的缺点?

  1. 不便于阅读
  2. 不便于异常处理

解决方案

  • promise 链式调用

    使用promise的链式调用解决回调地狱

doSomething()
  .then(result => doSomethingElse(result))
  .then(newResult => doThirdThing(newResult))
  .then(finalResult => {console.log('Got the final result:' + finalResult)})
  .catch(failureCallback)

终极解决方案

  • async/await

回调地狱的终极解决方案 async/await

async function request() {
  try{
    const result = await doSomething()
    const newResult = await doSomethingElse(result)
    const finalResult = await doThirdThing(newResult)
    console.log('Got the final result:' + finalResult)
  } catch (error) {
    failureCallback(error)
  }
}

2.3 Promise的相关API方法

1.Promise.resolve 方法:Promise.resolve(value)

value:将被 Promise 对象解析的参数,也可以是一个成功或失败的 Promise 对象
返回:返回一个带着给定值解析过的 Promise 对象,如果参数本身就是一个 Promise 对象,则直接返回这个 Promise 对象。

  1. 如果传入的参数为 非Promise类型的对象, 则返回的结果为成功promise对象
let p1 = Promise.resolve(521);
console.log(p1); // Promise {<fulfilled>: 521}

  1. 如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果
let p2 = Promise.resolve(new Promise((resolve, reject) => {
    // resolve('OK'); // 成功的Promise
    reject('Error');
}));
console.log(p2);
p2.catch(reason => {
    console.log(reason);
})

在这里插入图片描述

3.Promise.all 方法:Promise.all(iterable)

iterable:包含 n 个 promise 的可迭代对象,如 Array 或 String
说明:返回一个新的 promise,只有所有的 promise 都成功才成功,只要有一个失败了就直接失败

let p1 = new Promise((resolve, reject) => {
  resolve('OK');
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');

const result = Promise.all([p1, p2, p3]);
console.log(result);

3.Promise.race方法:Promise.race(iterable)

iterable:包含 n 个 promise 的可迭代对象,如 Array 或 String

说明:返回一个新的 promise,第一个完成的 promise 的结果状态就是最终的结果状态 谁先完成就输出谁(不管是成功还是失败)

const pRace = Promise.race([p1, p2, p3])
// 谁先完成就输出谁(不管是成功还是失败)
const p1 = new Promise((resolve, reject) => {
 setTimeout(() => {
   resolve(1)
 }, 1000)
})
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)

pRace.then(
value => {
   console.log('race onResolved()', value)
 },
reason => {
   console.log('race onRejected()', reason) 
 }
)
//race onResolved() 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值