Promise是什么?Promise怎么使用?回调地狱[通俗易懂]

Promise是什么?Promise怎么使用?回调地狱[通俗易懂]1、Promise的概念Promise是ES6提供的原生的类(构造函数),用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作)2、Promise的两个特点:1)、对象的状态不受外界影响。Promise有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。2)、一旦状态改变,就不会再变状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Reje

大家好,又见面了,我是你们的朋友全栈君。

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.net/135592.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Servlet 与 CGI 的比较「建议收藏」

    Servlet 与 CGI 的比较「建议收藏」首先什么是GCI,以下是百度给的定义。GCI:CGI 是Web 服务器运行时外部程序的规范,按CGI 编写的程序可以扩展服务器功能。CGI 应用程序能与浏览器进行交互,还可通过数据库API 与数据库服务器等外部数据源进行通信,从数据库服务器中获取数据。格式化为HTML文档后,发送给浏览器,也可以将从浏览器获得的数据放到数据库中。几乎所有服务器都支持CGI,可用任何语言编写CGI,包括流行的C、…

    2022年6月13日
    37
  • LC5软件激活成功教程用户口令[通俗易懂]

    LC5软件激活成功教程用户口令[通俗易懂]一、背景知识口令认证口令认证是身份认证的一种手段,计算机通过用户输入的用户名进行身份标识,通过访问·输入的口令对其是否拥有该用户对应的真实身份进行鉴别。口令攻击口令攻击可以通过强力攻击进行激活成功教程,也可以采用字典激活成功教程和字典混合激活成功教程的方法,根据是否掌握口令加密算法和口令数据的情况,采用在线激活成功教程和离线激活成功教程的方式。LC5LC5是一款口令激活成功教程工具,也可以被网络管理员用于检测Windows、Linux系统用户是否使用了不安全的密码,被普遍认为是当前最好、最快的Windows/Linux系统管理员账

    2022年7月24日
    10
  • MySQL最常用分组聚合函数「建议收藏」

    MySQL最常用分组聚合函数

    2022年2月10日
    43
  • 图片存储方案[通俗易懂]

    图片存储方案[通俗易懂]介绍在实际开发中,我们会有很多处理不同功能的服务器。例如:应用服务器:负责部署我们的应用数据库服务器:运行我们的数据库文件服务器:负责存储用户上传文件的服务器分服务器处理的目的是让服务器各司

    2022年7月4日
    41
  • webstorm2021激活码【注册码】

    webstorm2021激活码【注册码】,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月19日
    59
  • cxf实现webservice_简单框架

    cxf实现webservice_简单框架原文地址

    2022年9月21日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号