关于javascript中的promise的用法和注意事项(推荐)


Posted in Javascript onJanuary 15, 2021

一、promise描述

promise是javascript中标准的内置对象,用于表示一个异步操作的最终状态(是失败还是成功完成)及其结果值。它让你能够把异步操作最终成功或者失败的原因和响应的处理程序相关联,也就是说通过promise你可以自定义异步操作结束后该做什么。这样的话异步方法就和同步方法很类似,也有返回值,只不过这个返回值不是立即返回最终的值,而是返回一个promise,当promise的状态发生改变时,就会触发相应的处理程序。

一个promise无论什么时候都必然处于以下几种状态:1、待定(pending) 2、已兑现(fulfilled) 3、已拒绝(rejected)

promise创建之初是待定状态,它既咩有被兑现也咩有被拒绝,它用于包装还没有被添加promise支持的函数,包装后的函数变成异步操作函数,当操作结束时,会有两个两个分支,一个是已兑现,一个是已拒绝,如下图。已兑现状态的promise会调用后续的then方法,而已拒绝状态的promise既可以调用then方法,也可以被catch方法捕捉到。为什么then方法可以捕捉两个状态的promise呢?这里先不讲,下面再详细介绍。

关于javascript中的promise的用法和注意事项(推荐)

二、promise 的流程走向

上图是promise的流程图,从左到右可以得知一个promise在待定状态时通过两个分支走向分别进入then方法或者catch方法,这两个c方法都会返回promise,如果这个promise也被敲定了,而且其后也有then方法或者catch方法,则又会进入后续的then和catch中,直至咪有。

也就是说,promise和then或者catch可以形成一个异步操作的链式结构,结合js的事件循环机制,这使得js的优势更加明显,发展至今仍能在浏览器上频繁看到它的身影。

我们要注意流程的特点:

1、promise是对象,它的转移成功不取决于返回值,而取决于状态的敲定(是成功还是失败)

2、then和catch是函数,只要有promise状态发生了改变,该promise对应后面的then或者catch方法就会被调用,而这两个方法本身会返回一个promise,这个返回的promise又会影响这两个方法后面的then或者catch方法。两个方法的返回值一定是promise。

三、promise的创建

Promise对象是由关键字new及其构造函数来创建的。该构造函数会把一个叫做“处理器函数”(executor function)的函数作为它的参数。这个“处理器函数”接受两个函数——resolvereject——作为其参数。当异步任务顺利完成且返回结果值时,会调用resolve函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject函数。示例如下:

let myFirstPromise = new Promise(function(resolve, reject){
 //当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...)
 //在本例中,我们使用setTimeout(...)来模拟异步代码,实际编码时可能是XHR请求或是HTML5的一些API方法.
 setTimeout(function(){
  resolve("成功!"); //代码正常执行!
 }, 250);
});

myFirstPromise.then(function(successMessage){
 //successMessage的值是上面调用resolve(...)方法传入的值.
 //successMessage参数不一定非要是字符串类型,这里只是举个例子
 console.log("Yay! " + successMessage);
});

四、promise的优势

在promise未出现时,如果我们调用异步代码块的话是没有办法保持顺序的,而如果又出现了异步代码结果之间按序的需求,该如何实现呢?

以前的话通常都会将异步代码一层一层地内嵌来实现异步代码按序实现,但是这就造成了代码维护困难,开发难度增大

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

这就是经典的回调地狱。而如果使用了前面介绍的promise,那么代码就变成了容易维护的链式结构

五、then方法返回的promise类型

当一个Promise完成(fulfilled)或者失败(rejected)时,返回函数将被异步调用(由当前的线程循环来调度完成)。具体的返回值依据以下规则返回。如果then中的回调函数:

  • 返回了一个值,那么then返回的 Promise 将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
  • 没有返回任何值,那么then返回的 Promise 将会成为接受状态,并且该接受状态的回调函数的参数值为undefined
  • 抛出一个错误,那么then返回的 Promise 将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
  • 返回一个已经是接受状态的 Promise,那么then返回的 Promise 也会成为接受状态,并且将那个 Promise 的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。
  • 返回一个已经是拒绝状态的 Promise,那么then返回的 Promise 也会成为拒绝状态,并且将那个 Promise 的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
  • 返回一个未定状态(pending)的 Promise,那么then返回 Promise 的状态也是未定的,并且它的终态与那个 Promise 的终态相同;同时,它变为终态时调用的回调函数参数与那个 Promise 变为终态时的回调函数的参数是相同的。

六、catch捕捉的错误

catch能捕捉promise组合中出现的错误,但是有两种错误不能捕捉:

1、已决议的错误不能捕捉

//创建一个新的 Promise ,且已决议
var p1 = Promise.resolve("calling next");

var p2 = p1.catch(function (reason) {
 //这个方法永远不会调用
 console.log("catch p1!");
 console.log(reason);
});

p2.then(function (value) {
 console.log("next promise's onFulfilled"); /* next promise's onFulfilled */
 console.log(value); /* calling next */
}, function (reason) {
 console.log("next promise's onRejected");
 console.log(reason);
});

2、异步函数中抛出的错误不能捕捉

需要注意的是,作者亲手实践发现:promise包裹的异步函数执行成功后必须显式地调用resolve和reject方法才能触发后续then和catch方法,如果promise方法包裹的不是异步函数,是普通的同步函数,如果该同步代码运行出错,即便没有调用reject方法时,后面的catch方法仍然能够捕捉到这个错误,但如果同步代码没有出错,没有显式调用resolve方法转移的话,后续的then方法不会触发。

七、高级示例

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Document</title>
 <style>
  *{
   margin: 10px;
  }
  html{
   width: 100%;
   height: 100%;
  }
  body{
   width: 100%;
   height: 100%;
   display:flex;
   align-items: center;
   justify-content: center;
  }
  div.displaydatabox{
   width: 300px;
   height: 300px;
   border-radius: 50px;
   text-align: center;
   line-height: 300px;
   box-shadow: 0 0 10px 2px black;
  }
  div.button{
   width: 100px;
   height: 50px;
   border-radius: 21px;
   border: 2px solid orange;
   line-height: 50px;
   text-align: center;
   cursor: pointer;
  }
 </style>
</head>
<body>
 <div class="button">创建</div>
 <div class="button">输入文字</div>
 <div class="button">消失</div>
 <script lang="javascript">
  let buttonlist=document.querySelectorAll("div.button");
  let body=document.querySelector("body");
  buttonlist[0].onclick=function()
  {
   let div=document.createElement("div");
   div.className="displaydatabox";
   body.appendChild(div);
  }
  buttonlist[2].onclick=function()
  {
   let div=document.querySelector("div.displaydatabox");
   body.removeChild(div);
  }
  buttonlist[1].onclick=function(e)
  {
   let p1=new Promise((resolve,reject)=>
   {
    setTimeout(()=>{//用setTimeout函数模拟异步函数
     let div=document.querySelector("div.displaydatabox");
     div.textContent="这是promise实验";
     //reject(1);
     resolve(1);//调用resolve将调用第一个then
    },2000);
   }).then(function(resolve){
    return new Promise((resolve,reject)=>{
     console.log("这是状态咩有敲定的promise,所以不会调用后面所有的then方法");




//resolve(1)//没有调用resolve或者reject,所以状态未敲定。如果调用,将输出1和finally it has been called!!
    })
   .then(function(e){
    console.log(e);
   });
   }).catch(function(e)
   {
    console.log(e+" 没有块可以输入!!");
   }).then(()=>
   {
    console.log("finally it has been called!!");
   })
  }
 </script>
</body>
</html>

到此这篇关于关于javascript中的promise的用法和注意事项的文章就介绍到这了,更多相关js中promise用法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
Javascript级联下拉菜单以及AJAX数据验证核心代码
May 10 Javascript
本人自用的global.js库源码分享
Feb 28 Javascript
js改变embed标签src值的方法
Apr 10 Javascript
在Javascript中处理字符串之big()方法的使用
Jun 08 Javascript
JavaScript编写推箱子游戏
Jul 07 Javascript
javascript数组排序汇总
Jul 07 Javascript
简单的JS时钟实例讲解
Jan 13 Javascript
jquery事件绑定解绑机制源码解析
Sep 19 Javascript
jquery.Jcrop结合JAVA后台实现图片裁剪上传实例
Nov 05 Javascript
tangram.js库实现js类的方式实例分析
Jan 06 Javascript
vue3.0中使用postcss-pxtorem的具体方法
Nov 20 Javascript
JS中队列和双端队列实现及应用详解
Sep 29 Javascript
详解node.js创建一个web服务器(Server)的详细步骤
Jan 15 #Javascript
JavaScript中展开运算符及应用的实例代码
Jan 14 #Javascript
js中延迟加载和预加载的具体使用
Jan 14 #Javascript
JS中箭头函数与this的写法和理解
Jan 14 #Javascript
JavaScript this关键字的深入详解
Jan 14 #Javascript
Vue实现多页签组件
Jan 14 #Vue.js
如何在vue中使用HTML 5 拖放API
Jan 14 #Vue.js
You might like
如何在PHP中使用正则表达式进行查找替换
2013/06/13 PHP
php实现递归抓取网页类实例
2015/04/03 PHP
thinkPHP5框架导出Excel文件简单操作示例
2018/08/03 PHP
javascript 显示当前系统时间代码
2009/12/28 Javascript
jquery的ajax请求全面了解
2013/03/20 Javascript
Extjs 继承Ext.data.Store不起作用原因分析及解决
2013/04/15 Javascript
js Map List 遍历使用示例
2013/07/10 Javascript
JS中window.open全屏命令解析及使用示例
2013/12/11 Javascript
JavaScript中字符串与Unicode编码互相转换的实现方法
2015/12/18 Javascript
WEB前端实现裁剪上传图片功能
2016/10/17 Javascript
微信小程序 页面传参实例详解
2016/11/16 Javascript
javascript头像上传代码实例
2019/09/28 Javascript
JS实现简单日历特效
2020/01/03 Javascript
[04:26]2014DOTA2国际邀请赛-Newbee顺利进入胜者组决赛 独家专访战神7
2014/07/19 DOTA
Python常用列表数据结构小结
2014/08/06 Python
Python的Flask框架中实现分页功能的教程
2015/04/20 Python
Python的Tornado框架实现图片上传及图片大小修改功能
2016/06/30 Python
pyqt 实现QlineEdit 输入密码显示成圆点的方法
2019/06/24 Python
pymysql 开启调试模式的实现
2019/09/24 Python
Django框架HttpResponse对象用法实例分析
2019/11/01 Python
python多维数组分位数的求取方式
2020/03/03 Python
python删除某个目录文件夹的方法
2020/05/26 Python
Tensorflow--取tensorf指定列的操作方式
2020/06/30 Python
python 如何对logging日志封装
2020/12/02 Python
印度在线内衣和时尚目的地:Zivame
2017/09/28 全球购物
蹦床仓库:Trampoline Warehouse
2018/12/06 全球购物
Diamondback自行车:拥有你的冒险
2019/04/22 全球购物
中医专业应届生求职信
2013/11/17 职场文书
音乐学个人的自荐书范文
2013/11/26 职场文书
新任教师自我鉴定
2014/02/24 职场文书
卫校毕业生自我鉴定
2014/09/28 职场文书
先进单位申报材料
2014/12/25 职场文书
网络营销计划
2015/01/17 职场文书
维稳承诺书
2015/01/20 职场文书
行政经理岗位职责
2015/04/15 职场文书
进行数据处理的6个 Python 代码块分享
2022/04/06 Python