大家好,又见面了,我是你们的朋友全栈君。
1、Promise的概念
Promise是ES6提供的原生的类(构造函数), 用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作)
2、Promise的两个特点:
1)、对象的状态不受外界影响。
Promise 有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。
2)、一旦状态改变,就不会再变
状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected
3、Promise的作用
解决回调地狱的问题。
回调地狱的代码(使用setTimeout):
function fn1(cb){ console.log("fn1开始"); setTimeout(function(){ console.log("fn1的异步操作"); cb(); },1000); console.log("fn1结束"); } function fn2(cb){ console.log("fn2开始"); setTimeout(function(){ console.log("fn2的异步操作"); cb(); },1000); console.log("fn2结束"); } function fn3(cb){ console.log("fn3开始"); setTimeout(function(){ console.log("fn3的异步操作"); cb(); },1000); console.log("fn3结束"); } function fn4(){ console.log("fn4开始"); console.log("fn4结束"); } // 把fn1 里的代码全部(包括异步操作)执行完毕后,执行fn2,fn2的异步操作执行完毕,再执行fn3; fn1(function(){ fn2(function(){ fn3(fn4); }) });
Promise 对象可以将异步操作以同步操作的流程表达出来(使用链式的写法),避免了层层嵌套的回调函数。
如:函数fn1和fn2,当我们需要在fn1(fn1函数里有异步操作)调用结束后调用fn2,一般的解决方案是fn1(fn2)。而promise的做法是 fn1().then(fn2);即Promise将回调模式的主从关系调换了一个位置,变成了同等的只是顺序的关系
fn1().then(fn2).then(fn3).then(fn4)
4、Promise类的方法
console.dir(Promise)查看一下。
1、promise构造函数的参数是个函数 2、该函数(Promise的参数)的参数有两个:resolve,reject resolve 表示异步操作成功时,要调用的函数。是then函数的第一个参数 reject 表示异步操作失败时,要调用的函数。是then函数的第二个参数
new Promise(function(resolve, reject){ // 异步操作的代码 // 如果异步操作成功,调用resolve;如果失败,调用reject; });
1)、 对象方法:then、catch
then方法:
功能:把then方法的参数传给resolve和reject。 promise对象.then(resolve回调函数,reject回调函数);
参数:
then方法的第一个参数是resolve
then方法的第二个参数是reject。
返回值:promise对象本身,所以,then调用完毕后,还可以继续调用then(即:链式调用)
then方法的基本使用:
let p1 = new Promise(function(resolve,reject){ resolve(); reject(); }); p1.then(function(){ console.log("then方法的第一个参数"); },function(){ console.log("then方法的第二个参数"); });
带上异步操作
function fn(){ var p = new Promise(function(resolve, reject){ //做一些异步操作 setTimeout(function(){ console.log(‘异步执行完成'); resolve(‘姥姥的话就是你长大听不到的那些话');//这是then函数的参数; }, 2000); }); return p; } fn().then((str)=>{ console.log(str); },()=>{})
catch方法:
它和then的第二个参数一样,用来指定reject的回调,
function fn(){ var p = new Promise(function(resolve, reject){ //做一些异步操作 setTimeout(function(){ console.log(‘异步执行完成'); resolve(‘姥姥的话就是你长大听不到的那些话');//这是then函数的参数; }, 2000); }); return p; } fn() .then(()=>{}) .catch(()=>{})
Promise中then方法的数据传递
上一个then的返回值(结果)是下一个then的参数(输入)
function fn1(){ console.log("fn1开始"); let p = new Promise(function(resolve,reject){ setTimeout(function(){ console.log("fn1的异步操作"); resolve(3) },1000); }); console.log("fn1结束"); return p; } fn1().then(function(num){ console.log("第一次",num);//3 return num+1; }).then(function(num){ console.log("第二次",num);//4 return num+1; }).then(function(num){ console.log("第三次",num);//5 return num+1; });
2)、类方法: all , race
all方法:
功能: Promise.all可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据。返回的数据与传的参数数组的顺序是一样的。当所有的异步操作都成功才表示成功 。
参数:数组。数组里是若干个返回promise对象的函数(异步操作);
返回值:promise对象。promise对象的then方法的回调函数的参数是 所有promise对象的resolve的参数(数组形式)。
//示例一: function fn1(num){ console.log("fn1开始",num); let p = new Promise(function(resolve,reject){ setTimeout(function(){ console.log("fn1的异步操作",num); resolve("fn1异步的结果:"+num) },1000); }); console.log("fn1结束",num); return p; } Promise.all([fn1(1),fn1(2)]).then(function(result){ // 这个函数要执行,必须保证,fn1(1)和fn1(2)都成功,才调用。 // 参数result是数组,保存着多次异步操作的结果,也就是把多个异步操作中resolve函数的参数放到了result里 console.log("result",result); }); 示例二: function fn1(){ console.log("fn1开始"); let p = new Promise(function(resolve,reject){ setTimeout(function(){ console.log("fn1的异步操作"); resolve("fn1异步的结果") },1000); }); console.log("fn1结束"); return p; } function fn2(str){ console.log("fn2开始"); let p = new Promise(function(resolve,reject){ setTimeout(function(){ console.log("fn2的异步操作"); resolve("fn2异步的结果"); },3000); }); console.log("fn2结束"); return p; } Promise.all([fn1(),fn2()]).then(function(result){ console.log("result",result); //["fn1异步的结果","fn2异步的结果"] });
用Promise.all来执行,all接收一个数组参数,两个异步操作是并行执行的,等到它们都执行完后才会进到then里面。而两个异步操作返回的数据都在then里面,all会把所有异步操作的结果放进一个数组中传给then,就是上面的results
race方法:
功能:也是并发,但是,与all不同之处时,当一个异步操作完成(resolve或reject)时,就调用方法了。即:多个异步操作,同时执行,谁快就用谁的结果,所以,结果不再是数组。
function fn1(){ console.log("fn1开始"); let p = new Promise(function(resolve,reject){ setTimeout(function(){ console.log("fn1的异步操作"); resolve("fn1异步的结果") },1000); }); console.log("fn1结束"); return p; } function fn2(str){ console.log("fn2开始"); let p = new Promise(function(resolve,reject){ setTimeout(function(){ console.log("fn2的异步操作"); resolve("fn2异步的结果"); },3000); }); console.log("fn2结束"); return p; } Promise.race([fn1(),fn2()]).then(function(result){ console.log("result",result); //"fn1异步的结果" });
总结Promise的使用步骤
1、找到(曾经的)异步操作的代码,放在Prmoise构造函数的参数(函数)里 2、参数(函数)的第一个参数resolve是成功时调用的函数,对应then方法(函数)的第一个参数 3、参数(函数)的第二个参数reject是失败时调用的函数,对应then方法(函数)的第二个参数
5、 Promise封装AJAX
function ajaxUsePromise(obj){ let p = new Promise(function(resolve,reject){ let defaultObj = { url:"#", method:"get", params:"", isAsync:true } for(let key in defaultObj){ if(obj[key]!=undefined){ defaultObj[key] = obj[key]; } } let xhr =new XMLHttpRequest(); let urlAndParams = defaultObj.url; if(defaultObj.method.toLowerCase()=="get"){ urlAndParams += "?"+ defaultObj.params; } xhr.open(defaultObj.method,urlAndParams,defaultObj.isAsync); xhr.onreadystatechange = function(){ if(xhr.readyState==4){ if(xhr.status==200){ resolve&&resolve(xhr.responseText); }else{ reject&&reject("服务器出错了"); } } } }); if(defaultObj.method.toLowerCase()=="post"){ xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); xhr.send(defaultObj.params); }else{ xhr.send(); } return p; }
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/135592.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...