一、涉及技术

jquery、vue、php

二、Promise简介

MDN官方文档:Promise

三种状态:

  • Pending(进行中)
  • Resolved(已完成,又称 Fulfilled)
  • Rejected(已失败)

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

三、常用方法

  • Promise.resolve()
  • Promise.reject()
  • Promise.prototype.catch()
  • Promise.prototype.then()
  • Promise.all()
  • Promise.race()

四、简单示例

1、多个Promise使用

var promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve('hello');
    }, 1000);
});
promise.then(function(str) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve(str+' world');
        }, 1000);
    });
}).then(function(str) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve(str+' !');
        }, 1000);
    });
}).then(function(str) {
    console.log(str); // 3秒后打印 hello world !
});

2、catch与finaly

var promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        reject('异步报错~');
    }, 1000);
}).catch(function(err) { // 捕获reject暴露的错误
    console.log(err);
}).finally(function() { // 不管resolve/reject都执行
    console.log('complete');
});

五、前后端配合

1、单个Promise

后端数据

demo.php

// 获取随机字符串
function getRandChar($length) {
    $str = '';
    $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
    $max = strlen($strPol)-1;
    for($i=0;$i<$length;$i++){
        $str.=$strPol[rand(0,$max)];
    }
    return $str;
}
if($_GET['action'] == 'test') {
    $data = [
        ["name"=>getRandChar(6), "age"=>rand(1,50)],
        ["name"=>getRandChar(6), "age"=>rand(1,50)],
        ["name"=>getRandChar(6), "age"=>rand(1,50)],
        ["name"=>getRandChar(6), "age"=>rand(1,50)],
    ];
    echo json_encode($data);
}

前端页面

demo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>promise</title>
    <script src="jquery.min.js"></script>
    <script src="vue.min.js"></script>
</head>
<body>
    
    <div id="app">
        <ul>
            <li v-for="(item, index) in list">{{ index }} {{ item.name }}</li>
        </ul>
    </div>

    <script>
        var app = new Vue({
            el: '#app',
            data: {
                list: []
            },
            mounted: function() {
                var promise1 = new Promise(function(resolve, reject) {
                    $.ajax({
                        type: 'get',
                        url: 'demo.php?action=test',
                        dataType: 'json',
                        success: function(res) {
                            resolve(res);
                        },
                        error: function() {
                            reject('请求报错~');
                        }
                    });
                });
                // then(fn1, fn2)里有两个回调函数,一个是resove,一个是reject
                promise1.then(function(data) {
                    app.list = data;
                }, function(err) {
                    console.log(err);
                });
            }
        });     
    </script>
</body>
</html>

运行结果:

图片描述

2、Promise.all()

Promise.all(p1, p2, ...),此方法需要所有的promise都成功才成功。。
var promise1 = new Promise(function(resolve, reject) {
    $.ajax({
        type: 'get',
        url: 'demo.php?action=test',
        dataType: 'json',
        success: function(res) {
            resolve(res);
        },
        error: function() {
            reject('请求报错~');
        }
    });
});
var promise2 = new Promise(function(resolve, reject) {
    $.ajax({
        type: 'get',
        url: 'demo.php?action=test',
        dataType: 'json',
        success: function(res) {
            resolve(res);
        },
        error: function() {
            reject('请求报错~');
        }
    });
});
var promiseAll = Promise.all([promise1, promise2]);
promiseAll.then(function(data) {
    console.log(data);
}, function(err) {
    console.log(err);
});

结果

图片描述

如果我们把其中一个url 改成 demo2.php?action=test 就会请求失败~

Promise.all() 和 jquery的$.when() 有些类似

$.when()的写法

var ajax1 = $.ajax({type: 'get', url: 'demo1.php', data: {}, dataType: 'json'}),
    ajax2 = $.ajax({type: 'get', url: 'demo2.php', data: {}, dataType: 'json'}),
    ajax3 = $.ajax({type: 'get', url: 'demo3.php', data: {}, dataType: 'json'});
$.when([ajax1, ajax2, ajax3]).then(function(data1, data2, data3) {
    console.log(data1, data2, data3);
}, function() {
    console.log('%c 请求报错~', 'color: red');
});

3、Promise.race()

Promise.race(p1, p2, ...),这个方法会返回率先成功的那个,如果都不成功,则执行reject。
var promise1 = new Promise(function(resolve, reject) {
    $.ajax({
        type: 'get',
        url: 'demo.php?action=test',
        dataType: 'json',
        success: function(res) {
            resolve(res);
        },
        error: function() {
            reject('请求报错~');
        }
    });
});
var promise2 = new Promise(function(resolve, reject) {
    $.ajax({
        type: 'get',
        url: 'demo.php?action=test',
        dataType: 'json',
        success: function(res) {
            resolve(res);
        },
        error: function() {
            reject('请求报错~');
        }
    });
});

var promiseRase = Promise.race([promise1, promise2]);
promiseRase.then(function(data) {
    console.log(data);
}, function(err) {
    console.log(err);
});

4、多个ajax请求

var app = new Vue({
    el: '#app',
    data: {
        list: []
    },
    methods: {
        ajaxReq: function(resolve, reject) {
            $.ajax({
                type: 'get',
                url: 'demo.php?action=test',
                dataType: 'json',
                success: function(res) {
                    resolve(res);
                },
                error: function() {
                    reject('请求报错~');
                }
            });
        }
    },
    mounted: function() {
        var promise1 = new Promise((resolve, reject) => {
            this.ajaxReq(resolve, reject);
        });
        promise1.then((data)=> {
            console.log('第一次:', data);
            return new Promise((resolve, reject) => {
                this.ajaxReq(resolve, reject);
            });
        }).then((data) => {
            console.log('第二次:', data);
            return new Promise((resolve, reject) => {
                this.ajaxReq(resolve, reject);
            });
        }).then((data) => {
            console.log('第三次:', data);
        });
    }
});

这是使用了函数封装,实际上项目中,可能不是这样的,连贯操作,可能是下一个请求需要上一个请求的返回值

var promise1 = new Promise((resolve, reject) => {
    $.ajax({
        type: 'get',
        url: 'demo.php?action=test',
        dataType: 'json',
        success: function(res) {
            resolve(res, 2);
        },
        error: function() {
            reject('请求报错~');
        }
    });
});
promise1.then((data)=> {
    if(data.length > 0) {
        return new Promise((resolve, reject) => {
                    $.ajax({
                        type: 'get',
                        url: 'demo.php?action=test',
                        dataType: 'json',
                        success: function(res) {
                            resolve(res.concat(data)); // 因为resolve只能接口一个参数,所以concat了一下
                        },
                        error: function() {
                            reject('请求报错~');
                        }
                    });
                });   
    }
}).then((data1) => {
    console.log(data1);
});

图片描述


anchovy
1.9k 声望89 粉丝