摘要:上代码异步执行成功的构造函数接收一个函数参数,并传入两个参数,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。第一个回调函数是对象的状态变为时调用,第二个回调函数是对象的状态变为时调用。
这篇文章只解决三个问题。
什么是promise?
promise有什么用?
promise怎么用?
1.什么是promise?
对于ES6来说,就是一个构造函数,可以用new Promise( )来创建Promise实例。
2.promise有什么用?
先想象两个场景:
一,业务中,需要请求后台的两个接口,但是需要第一个返回成功结果之后再请求第二个接口,这是可能会写成下面这个样子,
var request = function(){ var xhr1 = new XMLHttpRequest(); xhr1.onreadystatechange = function(){ if(xhr1.readyState !== 4){ alert("第一步请求失败了,请重试!"); return; } if(xhr1.status === 200){ console.log("第一步请求成功了,我们开始下一步吧!"); var xhr2 = new XMLHttpRequest(); xhr2.open("GET", url); xhr2.onreadystatechange = function(){ if(xhr2.readyState !== 4){ alert("第二步请求失败了,请重试!"); return; } if(xhr2.status === 200){ //两次请求成功后做的一些事情.... } else { alert("第二步请求失败了,请重试!"); } }; xhr2.responseType = "json"; xhr2.setRequestHeader("Accept", "application/json2"); xhr2.send(); } else { alert("第一步请求失败了,请重试!"); } }; xhr1.responseType = "json"; xhr1.setRequestHeader("Accept", "application/json1"); xhr1.send(); }); } request();
上面代码用xhr对象实现了两次异步请求,代码很长。不过这仅仅是两层回调嵌套,想象一下更多的异步回调依赖有多可怕…
二,我们都知道,nodejs的一大特点就是事件驱动,那就肯定要利用事件的回调函数来处理逻辑,多层的回调嵌套也就在所难免。那么你的代码很可能就会写成这个德行,
async(1,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,final); }); }); }); }); }); }); }); })
就此你掉进了又长又丑的嵌套地狱。
咋办?
用promise(回答了“promise是干啥的”)。
咋用?
往下看。
3.promise 怎么用?
在学习怎么使用Promise的同时,需要不时接触几个关于它的知识点。能理解最好,理解不了用着用着就理解了。
首先需要了解的是每个Promise实例都有三种状态:
1.进行中状态 pending
2.成功状态 resolved
3.失败状态 rejected
同一时间下Promise实例只能有一种状态,且只能改变一次,改完之后就再也不能变了。
变化的途径只有两种,第一,从pending变为resolved;第二,从pending变为rejected。
接下来就一步步的完成一个promise的使用。
第一步,new一个Promise实例。上代码:
var promise = new Promise(function(resolve,reject){ if(/*异步执行成功*/){ resolve(value) } else { reject(error) } });
Promise的构造函数接收一个函数参数,并传入两个参数resolve,reject分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。执行resolve(),会将当前promise对象的状态更改为resolved,执行reject()会将当前promise对象的状态更改为rejected。
这时一个Promise对象已经创建完成,异步脚本的结果也已经被存在这个Promise对象中了,但它是成功是失败?我们怎么读取呢?
第二步,then方法。接着上代码:
var promise = new Promise(function(resolve,reject){ if(/*异步执行成功*/){ resolve(value); } else { reject(error); } }); promise.then(function(value){ console.log(value); },function(error){ console.log(error); })
每个Promise实例都有一个then方法,它就是处理Promise中存储的异步执行结果的方法。then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为Reject时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。
需要特别注意的是then方法的返回值还是一个Promise!这就意味着then方法是支持链式调用的。
第三步,catch方法。
catch方法等同于then(null,function(){}),也就是用来处理rejected状态下Promise数据的。关于catch个人认为记住两点就好。第一,用catch来处理rejected的Promise;第二,用catch来捕获之前所有链式调用中抛出的Error对象,注意是所有,包括Promise构造函数、then方法、链式调用的then方法、以及之前的catch,这些步骤抛出的错误都可以被catch捕获。
var promise = new Promise(function(resolve,reject){ if(false){ resolve(value); } else { reject(error); } }); promise .then(function(value){ console.log(value); }) .catch(function(reason){ console.log(error); })
上面代码会输出reject(error)传入的error值,也就是catch的第一种用法。
var promise = new Promise(function(resolve,reject){ if(true){ resolve(value); } else { reject(error); } }); promise .then(function(value){ console.log(value); console.log(x); }) .catch(function(reason){ console.log(reason); })
上面代码会将Promise的状态改为resolved,并执行then方法,在then方法中会抛出一个x变量未定义的错误,并由catch方法捕获到并打印出来,这就是catch的第二个用法。
至此实际上我们已经学会了Promise的基础应用。接下来再学习两个比较好用的方法。
第一个,Promise.all方法。
该方法能够并行运行异步方法,并在结果都返回之后进行统一处理,并返回一个新的Promise对象。
var p = Promise.all([p1, p2, p3]);
上面代码中,Promise.all方法接受一个“数组”作为参数,p1、p2、p3都是Promise对象的实例。
p的状态由p1、p2、p3决定,分成两种情况。
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。(fulfilled可以理解为resolved)
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
var p = Promise.all([p1,p2,p3]); p.then(function(results){ console.log(results) });
当打开网页时,需要预先加载各种资源如图片、flash以及各种静态文件,所有的都加载完后,我们再进行页面的初始化。这种场景是很适合使用Promise.all的。
第二个,Promise.race方法。
与all方法类似,同样是能够并行运行异步方法,并在结果都返回之后进行统一处理,并返回一个新的Promise对象。
var p = Promise.race([p1,p2,p3]);
上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数,也就是说谁执行的快就返回谁的。
race方法可以添加请求超时的限制。
//请求某个图片资源 function requestImg(){ var p = new Promise(function(resolve, reject){ var img = new Image(); img.onload = function(){ resolve(img); } img.src = "xxxxxx"; }); return p; } //延时函数,用于给请求计时 function timeout(){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ reject("图片请求超时"); }, 5000); }); return p; } Promise .race([requestImg(), timeout()]) .then(function(results){ console.log(results); }) .catch(function(reason){ console.log(reason); });
到这,关于Promise的三个问题已经解答完了,希望能够为大家学习Promise提供一点帮助。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/82256.html
摘要:从最开始的到封装后的都在试图解决异步编程过程中的问题。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。异步编程入门的全称是前端经典面试题从输入到页面加载发生了什么这是一篇开发的科普类文章,涉及到优化等多个方面。 TypeScript 入门教程 从 JavaScript 程序员的角度总结思考,循序渐进的理解 TypeScript。 网络基础知识之 HTTP 协议 详细介绍 HTT...
摘要:意味着操作成功完成。当调用方法的时候会设置一个状态,调用方法的时候会设置一个状态。返回是自定义的,状态由自己设但不能不给状态,不然不会执行下一个链详细文档文档 背景:在一个方法中处理一个复杂的异步操作时会涉及到多个异步处理,它们可能是层层嵌套导致这个方法异常的庞大,影响日后的代码维护和问题的查找 解决:在ES6中提供了一个Promise的对象,它以一种链式的写法将异步操作逻辑与异步返...
摘要:首先是一个构造器函数,使用它必须通过一个实例出来,并且出来的实例晕有一个内置的参数,这个参数是一个函数,这个参数拥有自己内置的两个参数,和,并且这两个参数也是两个函数异步操作成功上面这个就是一个最简单的对象属于的一个方法,里面的两个参数属于 首先promise是一个构造器函数,使用它必须通过new一个实例出来,并且new出来的实例晕有一个内置的参数,这个参数是一个函数,这个参数拥有自己...
摘要:首先是一个构造器函数,使用它必须通过一个实例出来,并且出来的实例晕有一个内置的参数,这个参数是一个函数,这个参数拥有自己内置的两个参数,和,并且这两个参数也是两个函数异步操作成功上面这个就是一个最简单的对象属于的一个方法,里面的两个参数属于 首先promise是一个构造器函数,使用它必须通过new一个实例出来,并且new出来的实例晕有一个内置的参数,这个参数是一个函数,这个参数拥有自己...
摘要:源码学习本篇为上一篇源码学习的补充,主要是来介绍和方法。那个率先改变的实例的返回值,就传递给的回调函数。基本介绍可见阮一峰老师的书籍。的状态由决定,分成两种情况。只有的状态都变成,的状态才会变成,此时的返回值组成一个数组,传递给的回调函数。 Promise源码学习(2) 本篇为上一篇源码学习(1)的补充,主要是来介绍Promise.all()和Promise.race()方法。闲话少叙...
阅读 1686·2021-11-23 09:51
阅读 3175·2021-09-26 10:21
阅读 800·2021-09-09 09:32
阅读 883·2019-08-29 16:06
阅读 3309·2019-08-26 13:36
阅读 773·2019-08-26 10:56
阅读 2565·2019-08-26 10:44
阅读 1145·2019-08-23 14:04