promise

有个东西叫回调地狱,promise就是来解决这个的.

看过的一些相关的技术文章

Promise介绍

then和catch方法

all和race方法

一些用法的例子


看过的一些相关的技术文章

http://liubin.github.io/promises-book/

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise


Promise介绍

Promise介绍

以前写一些异步的东西,都使用回调函数来执行的,这样的写法让人看起来很不舒服

比如写一个隔几秒就执行的一个回调的东西,然后在回调的时候,开始下一个异步

    setTimeout(function(){
        console.log(11111)
        setTimeout(function(){
            console.log(22222)
                setTimeout(function(){
                    console.log(33333)
                    setTimeout(function(){
                        console.log(44444)
                            setTimeout(function(){
                                console.log(55555)
                            },5000)
                    },4000)                    
                },3000)
        },2000)
    },1000)

这代码开起来维护起来都会很麻烦的,后来的后来,es6支持原生的Promise,jquery支持Deferred,Promise后,异步问题就容易多了

一个原生的Promise实现上面的代码

function setTime(t){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve();
        },t)   
    });
}
setTime(1000)
    .then(function(){
        console.log(11111)
        return setTime(1000);
    })
    .then(function(){
        console.log(22222)
        return setTime(2000);
    })
    .then(function(){
        console.log(33333)
        return setTime(3000);
    })
    .then(function(){
        console.log(44444)
        return setTime(4000);
    })
    .then(function(){
        console.log(55555)
    })      

什么是Promise?

Promise是抽象异步处理对象以及对其进行各种操作的组件。 其详细内容在接下来我们还会进行介绍,Promise并不是从JavaScript中发祥的概念。

Promise最初被提出是在 E语言中, 它是基于并列/并行处理设计的一种编程语言。

Promise的基本用法

new Promise(function(resolve, reject) { ... })

参数

带有 resolve 、reject两个参数的函数对象。 第一个参数用在处理执行成功的场景,第二个参数则用在处理执行失败的场景。 一旦我们的操作完成即可调用这些函数。

resolve是实例化后Promise用then里面调用的函数

reject是实例化后Promise用catch里面调用的函数

实例化的Promise有3个状态 :等待(pending)、已完成(fulfilled)、已拒绝(rejected)

实例化的Promise的状态,只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换

then和catch方法

then方法

then方法负责添加针对已完成的处理函数,同一个实例化后的Promise可以有多个then,then方法默认会返回当前的Promise,也可以自己重新实例化一个新的Promise

then方法对应实例化时候,function的resolve

catch方法

catch方法负责添加针对拒绝状态下处理函数,同一个实例化后的Promise可以有多个catch,catch方法默认会返回当前的Promise,也可以自己重新实例化一个新的Promise

catch方法对应实例化时候,function的resolve

一个例子

new Promise(function(resolve,rejected){
    var img = new Image();
    img.src="http://www.paipai.com/xx.jpg";   //这个会失败
    //img.src="https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png" //这个会成功
    img.onload = function(){
        resolve();
    }
    img.onerror = function(){
        rejected();
    }
})
.then(function(){
    console.log("图片加载成功!")
})
.catch(function(){
    console.log("图片加载失败!")
})

all和race方法

all方法

Promise.all 接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 .then 方法

这个比较好用,当有多个请求的时候,一起请求,一起处理

    return new Promise(function(resolve,rejected){
        setTimeout(function(){
            resolve();
        },t)
    })
}
Promise.all([setTime(1000),setTime(5000)])
.then(function(){
    console.log("5秒后打印!");
})

race方法

只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理。

function setTime(t){
    return new Promise(function(resolve,rejected){
        setTimeout(function(){
            resolve();
        },t)
    })
}
Promise.race([setTime(1000),setTime(5000)])
.then(function(){
    console.log("1秒后打印!");
})

一些用法的例子

Promise并非所有的浏览器都支持,比如ie就是不支持,幸好jquery也有类似的用法

1.一个异步里面接着另一个异步

原生Promise的实现

function setTime(t){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve();
        },t)   
    });
}
setTime(1000)
    .then(function(){
        console.log(11111)
        return setTime(1000);
    })
    .then(function(){
        console.log(22222)
        return setTime(2000);
    })
    .then(function(){
        console.log(33333)
        return setTime(3000);
    })
    .then(function(){
        console.log(44444)
        return setTime(4000);
    })
    .then(function(){
        console.log(55555)
    })    

jquery的实现

function setTime(t){
    return $.Deferred(function(dtd){
        setTimeout(function(){
            dtd.resolve();
        },t);
    });
}

setTime(2000)
    .then(function(){
        console.log(11111)
        return setTime(1000);
    })
    .then(function(){
        console.log(22222)
        return setTime(2000);
    })
    .then(function(){
        console.log(33333)
        return setTime(3000);
    })
    .then(function(){
        console.log(44444)
        return setTime(4000);
    })
    .then(function(){
        console.log(55555)
    })

2.多个ajax串行的请求(满足后面的请求依赖前面的请求的情况)

原生的实现

chorme浏览器可以直接在博客园下的console直接运行,如果接口都还在的

var urls = {
    sideRight : "http://www.cnblogs.com/aggsite/SideRight",
    userStats : "http://www.cnblogs.com/aggsite/UserStats"
}
function get(URL){
    return new Promise(function (resolve, reject) {
        var req = new XMLHttpRequest();
        req.open('GET', URL, true);
        req.onload = function () {
            if (req.status === 200) {
                resolve(req.responseText);
            } else {
                reject();
            }
        };
        req.onerror = function () {
            reject();
        };
        req.send();        
    });
}
get(urls.sideRight)
    .catch(function(){
        console.log("请求失败!!!");
    })
    .then(function(html){
        console.log(html);
        console.log("-----------------------------------------------------------")
        return get(urls.userStats);
    })
    .catch(function(){
        console.log("请求失败!!!");
    })
    .then(function(html){
        console.log(html)
    })

jquery的实现

var urls = {
    sideRight : "http://www.cnblogs.com/aggsite/SideRight",
    userStats : "http://www.cnblogs.com/aggsite/UserStats"
}

$.ajax({
        url      : urls.sideRight,
        type     : "get",
        dataType : "html"
    })
    .fail(function(){
        console.log("请求失败!!!");
    })
    .done(function(html){
        console.log(html)
        console.log("-----------------------------------------------------------")
        return $.ajax({
                    url      : urls.userStats,
                    type     : "get",
                    dataType : "html"
                });
    })
    .fail(function(){
        console.log("请求失败!!!");
    })
    .done(function(html){
        console.log(html)
    })

3.多个请求并行发送(适用于多个请求才能渲染出一个页面的情况)

原生Promise实现

var urls = {
    sideRight : "http://www.cnblogs.com/aggsite/SideRight",
    userStats : "http://www.cnblogs.com/aggsite/UserStats"
}
function get(URL){
    return new Promise(function (resolve, reject) {
        var req = new XMLHttpRequest();
        req.open('GET', URL, true);
        req.onload = function () {
            if (req.status === 200) {
                resolve(req.responseText);
            } else {
                reject(URL);
            }
        };
        req.onerror = function () {
            reject(URL);
        };
        req.send();        
    });
}

Promise.all([get(urls.sideRight),get(urls.userStats)])
    .then(function(htmlArr){
        console.log(htmlArr[0])
        console.log("-----------------------------------------------------------")
        console.log(htmlArr[1])
    })
    .catch(function(url){
        console.log(url+"  : 失败了");
    })

jquery实现

var urls = {
    sideRight : "http://www.cnblogs.com/aggsite/SideRight",
    userStats : "http://www.cnblogs.com/aggsite/UserStats1"
}

var $ajax1 = $.ajax({
    url      : urls.sideRight,
    type     : "get",
    dataType : "html"
})

var $ajax2 = $.ajax({
    url      : urls.userStats,
    type     : "get",
    dataType : "html"
})

$.when($ajax1,$ajax2)
    .done(function(response1Arr,response2Arr){
        console.log(response1Arr[0]);
        console.log("----------------------------");
        console.log(response2Arr[1])
    })
    .fail(function(res){
        console.log("请求失败了")
    });

注:当任意一个请求失败的时候,都会进入fail

原文地址:https://www.cnblogs.com/wtcsy/p/promise.html