es6 promise有几个状态
有3种状态:1、pending,表示正在进行中,该状态会进行初始化;2、fulfilled,表示已成功;3、rejected,表示已失败,会触发后续的catch回调函数。promise的状态发生改后就会凝固,不会再变,会一直保持这个结果。
本教程操作环境:windows7系统、ECMAScript 6版、Dell G3电脑。
Promise简介
Promise 是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理和更强大。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
从语法上说,Promise 是一个构造函数,从它可以获取异步操作的消息。
Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
Promise对象提供统一的接口,使得控制异步操作更加容易。
我们知道,es5是单线程语言,语句执行顺序由上往下,而项目前端对接后端时,需要用到ajax,而ajax是异步的,可能导致数据的交互产生延迟,不利于编程。而promise函数可以很好的解决这个问题。
Promise实例化
Promise
构造函数接受一个函数作为参数,该函数的两个参数分别是resolve
和reject
。而这两个参数是两个函数,由 JavaScript 引擎提供。
Promise对象代表一个异步操作,有三种状态: pending(进行中)、fulfilled(已成功)和rejected(已失败)。
初始化,状态:pending
当调用resolve(成功),状态:pengding=>fulfilled
当调用reject(失败),状态:pending=>rejected
状态发生改变之后就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。
状态变化:
1、pending -> resolved
2、pending -> rejected
状态的表现
pending状态不会触发then和catch
resolved状态会触发后续的then回调函数
rejected状态会触发后续的catch回调函数
then和catch改变状态
then正常情况下会返回resolved,报错则返回rejected
catch正常情况下会返回resolved,报错则返回rejected
const promise = new Promise(function(resolve,reject){ //...some code if(/*异步操作成功*/){ resolve(value); // 状态由pending变为fulfilled }else{ reject(error); // 状态由pending变为rejected } })
例如:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>测试</title> </head> <body> <script> let promise = new Promise(function (resolve, reject) { if (3 < 5) { resolve("是正确的"); } else { reject("是错误的"); } }) console.log(promise); </script> </body> </html>
结果:
Promise的原型方法
定义在Promise.prototype
中的方法,通过Promise实例可以直接调用。
1、Promise.prototype.then()
当状态由pending变为fulfilled的时候执行该回调函数,
参数:
最多需要有两个参数,Promise 的成功和失败情况的回调函数。
返回值:
返回一个新的Promise实例对象,因此可以使用链式调用。
当一个 Promise 完成(fulfilled)或者失败(rejected)时,返回函数将被异步调用(由当前的线程循环来调度完成)。具体的返回值依据以下规则返回。如果 then 中的回调函数:
返回了一个值,那么 then 返回的 Promise 将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
没有返回任何值,那么 then 返回的 Promise 将会成为接受状态,并且该接受状态的回调函数的参数值为 undefined。
throw抛出一个错误,那么 then 返回的 Promise 将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
返回一个已经是接受状态的 Promise,那么 then 返回的 Promise 也会成为接受状态,并且将那个 Promise 的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。
返回一个已经是拒绝状态的 Promise,那么 then 返回的 Promise 也会成为拒绝状态,并且将那个 Promise 的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
返回一个未定状态(pending)的 Promise,那么 then 返回 Promise 的状态也是未定的,并且它的终态与那个 Promise 的终态相同;同时,它变为终态时调用的回调函数参数与那个 Promise 变为终态时的回调函数的参数是相同的。
将上面的规则简单总结:
1、如果回调函数中的返回结果是promise对象,则对象状态由回调函数的执行结果决定
2、如果回到函数中的返回结果为非promise对象(无论是字符串、undefined…只要不是promise对象),对象状态均为成功,返回值为对象成功调用中的值。
3、throw抛出错误,状态为rejected
let p1 = new Promise((resolve, reject) => { resolve('成功!'); // 或者 // reject(new Error("出错了!")); }); p1.then(value => { console.log(value); // 成功! }, error => { console.log(error); // 出错了! });
2、Promise.prototype.catch()
当状态由pending变为rejected的时候执行该回调函数,
参数:
回调函数,回调函数的参数为reject函数传递过来的值
返回值:
返回一个新的Promise实例对象,因此可以使用链式调用。
// 抛出一个错误,大多数时候将调用catch方法 let p1 = new Promise(function(resolve, reject) { throw 'Uh-oh!'; }); p1.catch(function(e) { console.log(e); // "Uh-oh!" });
推荐使用catch方法,不要在then方法中定义rejected状态的回调函数;这是因为使用catch还可以捕获在then方法执行中存在的错误。
// bad promise.then(function(data) { // success }, function(err) { // error }); // good promise.then(function(data) { // success }) .catch(function(err) { // error })
3、Promise.prototype.finally()
finally() 方法返回一个Promise。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。这为在Promise是否成功完成后都需要执行的代码提供了一种方式。这避免了同样的语句需要在then()和catch()中各写一次的情况。
参数:
回调函数,不接收任何参数
返回值:
返回一个新的Promise实例对象
let p1 = new Promise(function(resolve, reject) { throw 'Uh-oh!'; }); p1.catch(function(e) { console.log(e); // "Uh-oh!" }).finally(function() { console.log('这段代码最终都会执行'); });
- promise封装ajax请求
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <title>promise基本使用</title> </head> <body> <script> let promise = new Promise(function(resolve,reject){ // ajax发送异步请求 $.ajax({ // 请求路径 url:'http://47.100.84.201:8888/carousel/findAll', // 成功回调 success(res){ console.log("成功回调",res); // 通过resolve将成功的回调传递出去 //resolve(res); }, // 失败回调 error(err){ console.log("失败回调",err); // 通过reject将失败的回调传递出去 //reject(err); } }) }) // 通过promise实例对象的实例方法对数据进行操作 promise .then(res => console.log("接收到resolve传递过来的数据" + res)) .catch(err => console.log("接收reject传递的数据" + err)) .finally(()=>{ console.log("无论成功还是失败都会调用!") }) </script> </body> </html>
分析:当在promise实例对象中ajax的两个回调函数中使用
console.log("成功回调",res)
和console.log("失败回调",err);
语句反映调用结果(成功或失败)时,浏览器控制台并不会执行then\catch\finally方法中的内容,因为此时then方法中并没有接收到来自ajax的res,catch方法有没有接收到来自ajax的err,所以并不会执行箭头函数中的语句。
当改为resolve(res);
和reject(err);
时结果如下:
- promise层级调用
假设有三个文件first.txt,second.txt,third.txt,读取文件
第一种方式:
使用普通方式进行层级读取文件(不推荐),如下:
const fs = require("fs"); fs.readFile('../FILE/first.txt',(err,data1) => { fs.readFile('../FILE/second.txt',(err,data2)=>{ fs.readFile('../FILE/second.txt',(err,data3)=>{ let result = data1 + '\t\n' + data2 + '\t\n' + data3; console.log(result); //... //如果后面还有其他文件呢,会导致回调地狱,代码会横向变得很宽很长,并且这里data不能重名,需要不断的取名字 }); }); });
第二种方式:
使用promise实现,解决缩进问题
const fs = require("fs"); // 初始化promise:读取第一个文件,使用resolve函数传递出去读取到的数据,用Promise对象接收 const promise = new Promise((resolve,reject)=>{ fs.readFile('../FILE/first.txt',(err,data)=>{ resolve(data); }) }) // 执行回调函数 promise.then(value => { //先看能不能获取到value值 // console.log(value); //输出的是buffer // console.log(value.toString()); //可以使用toString方法转化buffer为正常字符串 // then方法的返回值是一个promise对象,所以这里直接使用return返回一个promise对象 return new Promise((resolve,reject)=>{ // promise中的主要操作也是读取文件内容 fs.readFile('../FILE/second.txt',(err,data)=>{ // 将读取到的数据传递出去,这里将读取到的数据放到了数组中,一起传了出去 // value是初始化时读取文件first.txt的内容,data指的是当前读到的文件内容 resolve([value,data]); }) }) //使用链式调用方式继续调用,读取下一个文件的内容 }).then(value=>{ return new Promise((resolve,reject)=>{ fs.readFile('../FILE/third.txt',(err,data)=>{ // 将读取到的data通过push方法添加进数组中 // 这里的value是前面传过来的数组 value.push(data); resolve(value); }) }) }).then(value=>{ // 输出一一读取文件后的结果 console.log(value.toString()); // 这是第一个文件,这是第二个文件,这是第三个文件 // 文件间通过逗号分隔 })
虽然目前使用promise的代码量确实比较多,但却可以避免代码横向增多的问题,不会影响代码阅读
静态方法
定义在Promise中的方法,通过Promise可以直接调用。
1、Promise.all([p1,p2])
Promise.all用于将多个 Promise 实例,包装成一个新的 Promise 实例
参数:
数组,数组中的元素为Promise实例
返回值:
Promise实例,当p1,p2状态都为fulfilled时候,该实例的状态才为fulfilled,此时p1,p2的返回值组成一个数组,传递给该实例的回调函数;只要p1,p2的返回值有一个变为rejected,该实例状态为rejected。
const promise1 = Promise.resolve(3); //该方法用于将现有对象转化为Promise实例 const promise2 = 42; const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'foo'); }); Promise.all([promise1, promise2, promise3]).then((values) => { console.log(values); }); // expected output: Array [3, 42, "foo"]
2、Promise.race([p1,p2])
Promise.race用于将多个 Promise 实例,包装成一个新的 Promise 实例
参数:
数组,数组中的元素为Promise实例
返回值:
Promise实例,当p1,p2之中有一个实例率先改变状态,该实例的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给该实例的回调函数。(谁执行的快就返回谁)
const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, 'one'); }); const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'two'); }); Promise.race([promise1, promise2]).then((value) => { console.log(value); // Both resolve, but promise2 is faster }); // expected output: "two"
3、Promise.any([p1,p2])
用于将多个 Promise 实例,包装成一个新的 Promise 实例
参数:
数组,数组中的元素为Promise实例
返回值:
Promise实例,只要p1,p2状态有一个变为fulfilled,该实例的状态为fulfilled;p1,p2状态都变为rejected,该实例状态才为rejected。
const pErr = new Promise((resolve, reject) => { reject("总是失败"); }); const pSlow = new Promise((resolve, reject) => { setTimeout(resolve, 500, "最终完成"); }); const pFast = new Promise((resolve, reject) => { setTimeout(resolve, 100, "很快完成"); }); Promise.any([pErr, pSlow, pFast]).then((value) => { console.log(value); // pFast fulfils first }) // expected output: "很快完成"
4、Promise.resolve()
用于将现有对象转化为Promise实例
参数:
任意值
const promise1 = Promise.resolve(123); promise1.then((value) => { console.log(value); // expected output: 123 });
5、Promise.reject()
返回一个新的 Promise 实例,该实例的状态为rejected。
参数:
错误信息
Promise.reject(new Error('fail')).then(function() { // not called }, function(error) { console.log(error); // Stacktrace });
【相关推荐:javascript视频教程、web前端】
以上是es6 promise有几个状态的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

async是es7的。async和await是ES7中新增内容,是对于异步操作的解决方案;async/await可以说是co模块和生成器函数的语法糖,用更加清晰的语义解决js异步代码。async顾名思义是“异步”的意思,async用于声明一个函数是异步的;async和await有一个严格规定,两者都离不开对方,且await只能写在async函数中。

为了浏览器兼容。ES6作为JS的新规范,加入了很多新的语法和API,但现代浏览器对ES6新特性支持度不高,所以需将ES6代码转为ES5代码。在微信web开发者工具中,会默认使用babel将开发者ES6语法代码转换为三端都能很好支持的ES5的代码,帮助开发者解决环境不同所带来的开发问题;只需要在项目中配置勾选好“ES6转ES5”选项即可。

在日常生活中,我们常常会遇到承诺与兑现之间的问题。无论是在个人关系中,还是在商业交易中,承诺的兑现都是建立信任的关键。然而,承诺的利与弊也常常会引起争议。本文将探讨承诺的利与弊,并给出一些建议,如何做到言出必行。承诺的利是显而易见的。首先,承诺可以建立信任。当一个人信守承诺时,他会让别人相信自己是一个可信赖的人。信任是人与人之间建立起的纽带,它可以让人们更加

Vue是一款流行的前端框架,在开发应用时经常会遇到各种各样的错误和问题。其中,Uncaught(inpromise)TypeError是常见的一种错误类型。在本篇文章中,我们将探讨它的产生原因和解决方法。什么是Uncaught(inpromise)TypeError?Uncaught(inpromise)TypeError错误通常出现在

在es6中,暂时性死区是一个语法错误,是指let和const命令使区块形成封闭的作用域。在代码块内,使用let/const命令声明变量之前,该变量都是不可用的,在变量声明之前属于该变量的“死区”;这在语法上,称为“暂时性死区”。ES6规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。

Promise.resolve()详解,需要具体代码示例Promise是JavaScript中一种用于处理异步操作的机制。在实际开发中,经常需要处理一些需要按顺序执行的异步任务,而Promise.resolve()方法就是用来返回一个已经Fulfilled状态的Promise对象。Promise.resolve()是Promise类的一个静态方法,它接受一个

ES6 import会产生变量提升的现象。变量提升是将变量声明提升到它所在作用域的最开始的部分。js要经历编译跟执行阶段,在编译阶段的时候,会搜集所有的变量声明并且提前声明变量,而其他的语句都不会改变他们的顺序,因此,在编译阶段的时候,第一步就已经执行了,而第二部则是在执行阶段执行到该语句的时候才执行。
