Promise 的基本用法

(1) 创建 Promise 对象

Promise 对象代表一个异步操作,有三种状态 pending(进行中)、fufilled(已完成)和rejected(已失败)。

Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。

JS 复制代码
const promise = new Promis(function(resolve, reject){
   // ... some code
   if(/*异步操作成功*/){
      resolve(value);
   }else{
      reject(error);
   }
});

一般情况下都会使用 new Promise()来创建promise对象,但是也可以使用promise.resolve和promise.reject这两个方法:

  • Promise.resolve Promise.resolve(value)的返回值也是一个promise对象,可以对返回值进行.then调用,代码如下:
JS 复制代码
Promise.resolve(11).then(function(value){
   console.log(value); //打印出11
});

resolve(11)代码中,会让promise对象进入确定(resolve状态),并将参数11传递给后面then所指定的onFulfilled函数;

创建promise对象可以使用new Promise的形式创建对象,也可以使用Promise.resolve(value)的形式创建promise对象;

  • Promise.reject

Promise.reject也是new Promise的快捷形式,也创建一个promise对象。代码如下:

JS 复制代码
new Promise(function(resolve, reject){
   reject('运行失败!!');
});

下面是使用resolve方法和reject方法:

JS 复制代码
function testPromise(ready){
   return new Promise(function(resolve, reject){
      if(ready){
         resolve('成功');
      } else{
         reject('失败');
      }
   });
};
//方法调用
testPromise(true).then(function(msg){
   console.log(msg);
},function(error){
   console.log(error);
});

上面的代码的含义是给testPromise方法传递一个参数,返回一个promise对象,如果为true的话,那么调用promise对象中的resolve()方法,并且把其中的参数传递给后面的then第一个函数内,因此打印出 '成功', 如果为false的话,会调用promise对象中的reject()方法,则会进入then的第二个函数内,会打印'失败';

(2)Promise方法

Promise有五个常用的方法:then()、catch()、all()、race()、finally。下面就来看一下这些方法。

1. then()

当Promise执行的内容符合成功条件时,调用resolve函数,失败就调用reject函数。Promise创建完了,那该如何调用呢?

JS 复制代码
promise.then(function(value){
   // success
},function(error){
   //failure
});

then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象状态变为resolve时调用,第二个回调函数是Promise对象状态变为reject时调用。其中第二个参数可以省略。then方法返回的是一个新的Promise实例(不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

JS 复制代码
let promise = new Promise((resolve, reject) => {
   ajax('first').success(function(res){
      resolve(res);
   })
})
promise.then(res=>{
    return new Promise((resovle,reject)=>{
        ajax('second').success(function(res){
            resolve(res)
        })
    })
}).then(res=>{
    return new Promise((resovle,reject)=>{
        ajax('second').success(function(res){
            resolve(res)
        })
    })
}).then(res=>{
    
})

那当要写的事件没有顺序或者关系时,还如何写呢?可以使用all 方法来解决。

2. catch()

Promise对象除了有then方法,还有一个catch方法,该方法相当于then方法的第二个参数,指向reject的回调函数。不过catch方法还有一个作用,就是在执行resolve回调函数的时候,如果出现错误,抛出异常,不会停止运行,而是进入到catch方法中。

JS 复制代码
p.then((data) => {
     console.log('resolved',data);
},(err) => {
     console.log('rejected',err);
     }
); 
p.then((data) => {
    console.log('resolved',data);
}).catch((err) => {
    console.log('rejected',err);
});

3. all()

all方法可以完成并行任务, 它接收一个数组,数组的每一项都是一个promise对象。当数组中所有的promise的状态都达到resolved的时候,all方法的状态就会变成resolved,如果有一个状态变成了rejected,那么all方法的状态就会变成rejected。

JS 复制代码
let promise1 = new Promise((resolve,reject)=>{
	setTimeout(()=>{
       resolve(1);
	},2000)
});
let promise2 = new Promise((resolve,reject)=>{
	setTimeout(()=>{
       resolve(2);
	},1000)
});
let promise3 = new Promise((resolve,reject)=>{
	setTimeout(()=>{
       resolve(3);
	},3000)
});
Promise.all([promise1,promise2,promise3]).then(res=>{
    console.log(res);
    //结果为:[1,2,3] 
})

调用all方法时的结果成功的时候是回调函数的参数也是一个数组,这个数组按顺序保存着每一个promise对象resolve执行时的值。

(4)race()

race方法和all一样,接受的参数是一个每项都是promise的数组,但是与all不同的是,当最先执行完的事件执行完之后,就直接返回该promise对象的值。如果第一个promise对象状态变成resolved,那自身的状态变成了resolved;反之第一个promise变成rejected,那自身状态就会变成rejected。

JS 复制代码
let promise1 = new Promise((resolve,reject)=>{
	setTimeout(()=>{
       reject(1);
	},2000)
});
let promise2 = new Promise((resolve,reject)=>{
	setTimeout(()=>{
       resolve(2);
	},1000)
});
let promise3 = new Promise((resolve,reject)=>{
	setTimeout(()=>{
       resolve(3);
	},3000)
});
Promise.race([promise1,promise2,promise3]).then(res=>{
	console.log(res);
	//结果:2
},rej=>{
    console.log(rej)};
)

那么race方法有什么实际作用呢?当要做一件事,超过多长时间就不做了,可以用这个方法来解决:

JS 复制代码
javascript
复制代码Promise.race([promise1,timeOutPromise(5000)]).then(res=>{})

5. finally()

finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的

JS 复制代码
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

上面代码中,不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数。

下面是一个例子,服务器使用 Promise 处理请求,然后使用finally方法关掉服务器。

JS 复制代码
server.listen(port)
  .then(function () {
    // ...
  })
  .finally(server.stop);

finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。finally本质上是then方法的特例:

JS 复制代码
promise
.finally(() => {
  // 语句
});
// 等同于
promise
.then(
  result => {
    // 语句
    return result;
  },
  error => {
    // 语句
    throw error;
  }
);

上面代码中,如果不使用finally方法,同样的语句需要为成功和失败两种情况各写一次。有了finally方法,则只需要写一次。

相关推荐
leoZ2311 分钟前
2026-09-10-静态扫描连错三次-用运行环境当裁判
前端·javascript·vue.js·人工智能·opencv·机器学习·数据挖掘
Maxkim4 分钟前
我把一个"会自己查资料"的 AI 助手塞进了浏览器侧边栏,开源了
前端·javascript
mONESY11 分钟前
LangChain 结构化输出进阶:with_structured_output 做了什么,以及它为什么流不起来
javascript
计算机魔术师29 分钟前
英伟达要投100亿美元入股Anthropic,史上最大IPO的底牌
前端
hanchenxing1 小时前
自动化脚本“卡住无输出“怎么办: 一次 WebSocket 挂死的排查与自愈模板
运维·javascript·chrome·websocket·自动化·自动化爬虫
yume_sibai1 小时前
02-Flutter进阶开发
前端·flutter
津津有味道1 小时前
Web网页写网址到424DNA标签Javascrip源码
javascript·nfc·424dna·写网址·加密提交
a1117762 小时前
莱茵生命终端 网页 html
前端·开源
水月清辉2 小时前
CSS 常用语法详解
前端·css
Eric_见嘉3 小时前
打开这个 VSC 设置「组件引用位置」和数量就都清楚了
前端·typescript·visual studio code