大家好,又见面了,我是你们的朋友全栈君。
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;
}
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/135592.html原文链接:https://javaforall.cn