关于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 相关文章推荐
Jquery Ajax.ashx 高效分页实现代码
Oct 20 Javascript
IE6下CSS图片缓存问题解决方法
Dec 09 Javascript
JSON为什么那样红为什么要用json(另有洞天)
Dec 26 Javascript
jquery仿QQ商城带左右按钮控制焦点图片切换滚动效果
Jun 27 Javascript
JS+CSS实现可以凹陷显示选中单元格的方法
Mar 02 Javascript
如何改进javascript代码的性能
Apr 02 Javascript
jQuery实现页面滚动时智能浮动定位
Jan 08 Javascript
微信小程序 五星评价功能的实现
Mar 09 Javascript
webpack配置之后端渲染详解
Oct 26 Javascript
JavaScript使用闭包模仿块级作用域操作示例
Jan 21 Javascript
vue实现可视化可拖放的自定义表单的示例代码
Mar 20 Javascript
Vue向后台传数组数据,springboot接收vue传的数组数据实例
Nov 12 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转成EXE文件
2006/10/09 PHP
PHP base64编码后解码乱码的解决办法
2014/06/19 PHP
Nginx实现反向代理
2017/09/20 Servers
基础的prototype.js常用函数及其用法
2007/03/10 Javascript
JS代码优化技巧之通俗版(减少js体积)
2011/12/23 Javascript
JS对话框_JS模态对话框showModalDialog用法总结
2014/01/11 Javascript
jquery实现邮箱自动补全功能示例分享
2014/02/17 Javascript
js简单的弹出框有关闭按钮
2014/05/05 Javascript
jquery实现华丽的可折角广告代码
2015/09/02 Javascript
JavaScript+html5 canvas绘制的圆弧荡秋千效果完整实例
2016/01/26 Javascript
你所未知的3种Node.js代码优化方式
2016/02/25 Javascript
BootStrap的alert提示框的关闭后再显示怎么解决
2016/05/17 Javascript
老生常谈javascript的类型转换
2016/10/12 Javascript
用js实现博客打赏功能
2016/10/24 Javascript
JS简单实现滑动加载数据的方法示例
2017/10/18 Javascript
vue项目中引入noVNC远程桌面的方法
2018/03/05 Javascript
js实现按钮开关单机下拉菜单效果
2018/11/22 Javascript
JQuery样式与属性设置方法分析
2019/12/07 jQuery
Python编程判断这天是这一年第几天的方法示例
2017/04/18 Python
Python 多核并行计算的示例代码
2017/11/07 Python
VScode编写第一个Python程序HelloWorld步骤
2018/04/06 Python
python基于物品协同过滤算法实现代码
2018/05/31 Python
详解Python 调用C# dll库最简方法
2019/06/20 Python
python的mysql数据库建立表与插入数据操作示例
2019/09/30 Python
TensorFlow学习之分布式的TensorFlow运行环境
2020/02/05 Python
python使用正则表达式去除中文文本多余空格,保留英文之间空格方法详解
2020/02/11 Python
python通过函数名调用函数的几种场景
2020/09/23 Python
python中round函数保留两位小数的方法
2020/12/04 Python
HTML5本地存储localStorage、sessionStorage基本用法、遍历操作、异常处理等
2014/05/08 HTML / CSS
html5版canvas自由拼图实例
2014/10/15 HTML / CSS
酒店服务与管理毕业生求职信
2013/11/02 职场文书
六查六看自检自查剖析材料
2014/10/14 职场文书
群众路线教育实践活动实施方案
2014/10/31 职场文书
家长对学校的意见和建议
2015/06/03 职场文书
初任公务员培训心得体会
2016/01/08 职场文书
2016年党员公开承诺书格式范文
2016/03/24 职场文书