关于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 相关文章推荐
一个可以兼容IE FF的加为首页与加入收藏实现代码
Nov 02 Javascript
jQuery学习笔记(2)--用jquery实现各种模态提示框代码及项目构架
Apr 08 Javascript
关于页面嵌入swf覆盖div层的问题的解决方法
Feb 11 Javascript
用js模拟struts2的多action调用示例
May 19 Javascript
jQuery Mobile中的button按钮组件基础使用教程
May 23 Javascript
ES6中的数组扩展方法
Aug 26 Javascript
vue 中滚动条始终定位在底部的方法
Sep 03 Javascript
详解Webpack loader 之 file-loader
Nov 07 Javascript
vue自定义键盘信息、监听数据变化的方法示例【基于vm.$watch】
Mar 16 Javascript
3分钟了解vue数据劫持的原理实现
May 01 Javascript
适合前端Vue开发童鞋的跨平台Weex的使用详解
Oct 16 Javascript
JS XMLHttpRequest原理与使用方法深入详解
Apr 30 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
ThinkPHP自动验证失败的解决方法
2011/06/09 PHP
解析PHP高效率写法(详解原因)
2013/06/20 PHP
php更新mysql后获取改变行数的方法
2014/12/25 PHP
谈谈php对接芝麻信用踩的坑
2016/12/01 PHP
PHP静态成员变量和非静态成员变量详解
2017/02/14 PHP
laravel http 自定义公共验证和响应的方法
2019/09/29 PHP
用js自动判断浏览器分辨率的代码
2007/01/28 Javascript
经常用到的JavasScript事件的翻译
2007/04/09 Javascript
基于jquery的网页SELECT下拉框美化代码
2010/10/28 Javascript
使用GruntJS构建Web程序之合并压缩篇
2014/06/06 Javascript
JavaScript使用Max函数返回两个数字中较大数的方法
2015/04/06 Javascript
JavaScript实现的Tween算法及缓冲特效实例代码
2015/11/03 Javascript
Vue.js中用v-bind绑定class的注意事项
2016/12/13 Javascript
微信小程序picker组件关于objectArray数据类型的绑定方法
2019/03/13 Javascript
简单了解小程序+node梳理登陆流程
2019/06/24 Javascript
Vue中的循环及修改差值表达式的方法
2019/08/29 Javascript
layui当点击文本框时弹出选择框,显示选择内容的例子
2019/09/02 Javascript
vue实现标签云效果的示例
2020/11/09 Javascript
Python实现批量转换文件编码的方法
2015/07/28 Python
详解Python中的Descriptor描述符类
2016/06/14 Python
使用Python脚本和ADB命令实现卸载App
2017/02/10 Python
浅谈Python脚本开头及导包注释自动添加方法
2018/10/27 Python
PyTorch的torch.cat用法
2020/06/28 Python
高级运动鞋:GREATS
2019/07/19 全球购物
介绍一下ICMP(Internet Control Message Protocol)Internet控制信息协议
2016/11/26 面试题
工程造价自荐信
2013/10/09 职场文书
竞选村长演讲稿
2014/04/28 职场文书
无毒社区工作方案
2014/05/23 职场文书
机械工程师岗位职责
2014/06/16 职场文书
三好学生事迹材料
2014/12/24 职场文书
教师节感谢信
2015/01/22 职场文书
鸟的天堂导游词
2015/01/31 职场文书
react中props 的使用及进行限制的方法
2021/04/28 Javascript
解决使用了nginx获取IP地址都是127.0.0.1 的问题
2021/09/25 Servers
Python学习之迭代器详解
2022/04/01 Python
VUE解决跨域问题Access to XMLHttpRequest at
2022/05/06 Vue.js