您现在的位置是:首页 >学无止境 >Promise是什么?网站首页学无止境

Promise是什么?

瑶瑶旺仔 2024-06-17 10:32:04
简介Promise是什么?

目录

Promise对象的特点

Promise.resolve()

Promise.reject()

Promise.try()

Promise.all()

Promise.race()

Promise.allSettled()

Promise.any()

区分:


Promise是异步编程的一种解决方案,它就是一个容器,里面保存着某个未来才会结束的事件的结果,从语法上说,Promise就是一个对象,从他可以获取异步操作的消息。

Promise对象的特点

  1. 对象的状态不受外界的影响:Promise对象代表一个异步操作,有三种状态:pending、fullfilled、rejected,只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态

  2. 一旦改变,就不会再变,任何时候都可以得到这个结果

Promise.resolve()

将现有对象转为Promise对象。   

Promise.resolve('foo')
//等价于
new Promise(resolve=>resolve('foo'))

  参数:

  1. 是一个Promise实例

    如果参数是Promise实例,那么Promise.resolve将不做任何修改,原封不动地返回这个实例。
  2. 是一个thenable对象

    thenable对象指的是具有then方法的对象,如:
let thenable={
    then:function(resolve,reject){
        resolve(42)
    }
}

         Promise.resolve方法会将这个对象转为Promise对象,然后就立即执行thneable对象的then方法

     3.不是具有then方法的对象,或根本就不是对象

        Promise.resolve方法返回一个新的Promise对象,状态为resolved。

const p=Promise.resolve('hello')
p.then((s)=>{
    console.log(s)
})

     4.不带有任何参数

        Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的Promise对象。

        如果希望得到一个Promise对象,比较方便的方法就是直接调用Promise.resolve()方法,如下:

const p=Promise.resolve();
p.then(()=>{
	//...
})

         立即resolve()的Promise对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时。

setTimeout(function () {
  console.log('three');
}, 0);
Promise.resolve().then(function () {
  console.log('two');
});
console.log('one');
// one
// two
// three

js的执行顺序:先同步再异步。

异步中任务队列的执行顺序:先微任务队列,再宏任务队列。

Promise中的resolve、reject属于微任务队列,settimeout属于宏任务队列。

Promise.reject()

Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态是rejected

const p=Promise.reject('出错了')
//等价于
const p=new Promise((resolve,reject)=>{
	reject("出错了")
})
p.then(null,(s)=>{
	console.log(s)//出错了
})

 Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。

const thenable={
    then(resolve,reject){
        reject("出错了")
    }
}

Promise.reject(thenable)
.catch(e=>{
	console.log(e===thenable)//true
})

Promise.try()

让同步函数同步执行,异步函数异步执行,并让它们具有统一的·API

有两种写法:

  1. async函数

const f=()=>console.log('now')
(async()=>f())()//同步函数写法
(async()=>f())().then(...)//异步函数写法
console.log('next')

//now
//next

     2.new Promise()

const f=()=>console.log('now')
(
	()=>new Promise(resolve=>resolve(f()))
)()
cosole.log('next')
//now
//next
  • 上面代码使用的是立即执行的匿名函数,执行new Promise(),这种情况下,同步函数也是同步执行的。

  • 还可以用Promise.try方法代替上面的写法:

const f=()=>console.log('now')
Promise.try(f)
console.log('next')
//now
//next
  • 还可以统一用peomise.catch()捕获所有同步和异步的错误:

Promise.try(() => database.users.get({id: userId}))
  .then(...)
  .catch(...)

Promise.all()

Promise.all()方法用于将多个Promise实例,包装成一个新的Promise实例。

const p=Promise.all([p1,p2,p3])
  • Promise.all()的参数可以不是数组,但必须有Iterator接口,且返回的每个成员都是Pomise实例

  • p的状态由p1、p2、p3决定,分成两种情况

    1. 只有p1、p2、p3的状态都变成fullfilled,p的状态才会变成fullfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数

    2. 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数

const databasePromise = connectDatabase();
const booksPromise = databasePromise
  .then(findAllBooks);
const userPromise = databasePromise
  .then(getCurrentUser);
Promise.all([
  booksPromise,
  userPromise
])
.then(([books, user]) => pickTopRecommendations(books, user));

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

Promise.race()

Promise.race()方法同样是将多个Promise实例,包装成一个新的Promise实例

const p=Promise.race([p1,p2,p3])

        上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变,率先改变的Promise实例的返回值传递给p的回调函数。

        Promise.all()方法的参数与Promise.all()方法的一样,如果不是Promise实例,就会先调用Promise.resolve方法,将参数转为Promise实例。

const p = Promise.race([
  fetch('/resource-that-may-take-a-while'),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
]);
p
.then(console.log)
.catch(console.error);

        上面代码中race有两个参数:fetch('/resource-that-may-take-a-while')和new Promise(function (resolve, reject) { setTimeout(() => reject(new Error('request timeout')), 5000) }),如果在5秒之内第一个函数没有返回结果,就会因为执行第二个函数,导致Promise的状态变为reject。

Promise.allSettled()

Promise.allSettled()方法接受一组Promise实例作为参数,包装成一个新的Promise实例,只有等到所有这些参数实例都返回结果,不管是fullfilled还是rejected,包装实例才会结束。当我们不关心异步操作的结果,只关心这些操作有没有结束,这时,Promise.allSettled()方法就派上用场了。

Promise.any()

Promise.any()方法接收一组Promise实例作为参数,包装成一个新的Promise实例,只要有一个参数实例变成fullfilled状态,包装实例就会变成fullfilled状态,如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态,Promise的状态总是fullfilled。

区分易混淆:

在这里我们区分一下Promise.all()、Promise.race()、Promise.allSettled()、Promise.any():

  • Promise.all():参数实例状态都变成fullfilled,Promise的状态才会变成fullfilled,只要有一个变成rejected,Promise的状态就会变成rejected。

  • Promise.race():参数实例率先改变状态的,Promise的状态会跟着改变。

  • Promise.allSettled():当参数实例发出的请求结束时,不管其是fullfilled还是rejected,Promise的状态总是fullfilled

  • Promise.any():只要有一个参数实例变成fullfilled,Promise状态就会变成fullfilled,如果所有参数实例状态都变成rejected状态,Promise状态就会变成rejected

文档:ES6 入门教程

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。