关于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 相关文章推荐
从新浪弄下来的全屏广告代码 与使用说明
Mar 15 Javascript
js触发asp.net的Button的Onclick事件应用
Feb 02 Javascript
JSON传递bool类型数据的处理方式介绍
Sep 18 Javascript
JS实现仿腾讯微博无刷新删除微博效果代码
Oct 16 Javascript
使用伪命名空间封装保护独自创建的对象方法
Aug 04 Javascript
详解Vue2中组件间通信的解决全方案
Jul 28 Javascript
ExtJs使用自定义插件动态保存表头配置(隐藏或显示)
Sep 25 Javascript
React项目动态设置title标题的方法示例
Sep 26 Javascript
使用vue根据状态添加列表数据和删除列表数据的实例
Sep 29 Javascript
puppeteer实现html截图的示例代码
Jan 10 Javascript
jquery图片预览插件实现方法详解
Jul 18 jQuery
vue组件传值的实现方式小结【三种方式】
Feb 05 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
摘自织梦CMS的HTTP文件下载类
2015/08/08 PHP
php外部执行命令函数用法小结
2016/10/11 PHP
用Javascript 和 CSS 实现脚注(Footnote)效果
2009/09/09 Javascript
js离开或刷新页面检测(且兼容FF,IE,Chrome)
2014/03/05 Javascript
JavaScript中的迭代器和生成器详解
2014/10/29 Javascript
简要了解jQuery移动web开发的响应式布局设计
2015/12/04 Javascript
JavaScript实现带播放列表的音乐播放器实例分享
2016/03/07 Javascript
jQuery的each循环用法简单示例
2016/06/12 Javascript
JavaScript 对象详细整理总结
2016/09/29 Javascript
JS瀑布流实现方法实例分析
2016/12/19 Javascript
Easyui笔记2:实现datagrid多行删除的示例代码
2017/01/14 Javascript
js 输入框 正则表达式(菜鸟必看教程)
2017/02/19 Javascript
解决html input验证只能输入数字,不能输入其他的问题
2017/07/21 Javascript
Java设计中的Builder模式的介绍
2018/03/22 Javascript
微信小程序云开发(数据库)详解
2019/05/17 Javascript
vue开发拖拽进度条滑动组件
2019/09/21 Javascript
TypeScript 运行时类型检查补充工具
2020/09/28 Javascript
[06:23]2014DOTA2西雅图国际邀请赛 小组赛7月12日TOPPLAY
2014/07/12 DOTA
python抓取网页图片并放到指定文件夹
2014/04/24 Python
Python2.x版本中cmp()方法的使用教程
2015/05/14 Python
Django自定义分页效果
2017/06/27 Python
浅谈python中copy和deepcopy中的区别
2017/10/23 Python
python实现对excel进行数据剔除操作实例
2017/12/07 Python
python切片及sys.argv[]用法详解
2018/05/25 Python
python标记语句块使用方法总结
2019/08/05 Python
Python实现Restful API的例子
2019/08/31 Python
Flesh Beauty官网:露华浓集团旗下彩妆品牌
2021/02/15 全球购物
Why do we need Unit test
2013/01/03 面试题
销售自我评价
2013/10/22 职场文书
思想政治教育专业个人求职信范文
2013/12/20 职场文书
银行学习十八大感想
2014/01/11 职场文书
个人优缺点自我评价
2014/01/27 职场文书
党员服务承诺书
2014/05/28 职场文书
退休党员个人对照检查材料思想汇报
2014/09/29 职场文书
财务工作检讨书
2014/10/29 职场文书
《称赞》教学反思
2016/02/17 职场文书