JavaScript 的 Promise

先看这个 http://www.html5rocks.com/zh/tutorials/es6/promises/#toc-api  【JavaScript Promise 浏览器支持的Promise】

deferred与Promise  http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/  【deferred怎么用】

以及 http://www.cnblogs.com/silin6/p/4309925.html

http://www.shakyshane.com/javascript/2013/11/16/making-promises-with-javascript/  【deferred 与 Timeout】

还有一个PPT 很棒  http://lucifier129.github.io/nodeppt/20150528/promise.htm 【其中提到jQuery不支持的情况是1.7.2版本以及之前的版本  1.8.0之后都已经支持】

    // jQuery对promise的实现叫做 deferred
    var ajax = $.ajax({
        url: 'http://fanyi.youdao.com/openapi.do',
        type: 'GET',
        dataType: 'jsonp',
        data: {
            'keyfrom': 'rakustrans',
            'key': '1506707246',
            'type': 'data',
            'doctype': 'jsonp',
            'version': '1.1',
            'q': 'synchronize'
        },
    });
    //PS  $.get对于dataType可以智能判断  对于json后缀的 可以自动将返回值转为JSON对象 无需parse()
    $.get('story.json').then(function(json){
        console.log(json);
    })
    //ajax本身就是一个延迟对象   也就是deferred
    //https://api.jquery.com/category/deferred-object/
    //所以ajax可以通过.promise() 返回一个promise
    //ajax本身是一个thenable的对象  所以可以使用then
    ajax.then(function(data) {
        console.log(data);
        var rs = $.extend({},data);
        rs.newKey = 'newKey';
        return rs;
    }, function(err) {
        console.log(err);
    }).then(function(data){
        console.log(data);
    },function(err){
        console.log(err);
    });
    //和上面效果一样
    //resolve的值在resolve间
    ajax.promise().then(function(data) {
        console.log(data);
        var rs = $.extend({},data);
        rs.newKey = 'newKey';
        return rs; // 注意 jQ1.7.2的then是不能传递返回值的 //从jQ 1.8 版本之后都支持返回值和promise嵌套
    }, function(err) {
        console.log(err);
    }).then(function(data){
        console.log();
    },function(data){
        console.log();
    });

    $.get('story.txt').then(function(data){
        console.log(data); //字符串
        return JSON.parse(data); //jQ1.7.2 deferred不能传递
    }).then(function(data){
        console.log(data); //jQ1.7.2 deferred不能传递 也就是说不论前一个then的resolve返回什么值  这里data都是第一个then的data
        //所以 jQ1.7.2这里得到的值是字符串 而不是parse后的对象
    });


    $.get('story.txt').then(function(data){
        console.log(data);
        // return $.get('story.json');
        return $.get('story.json').then(function(json){
            json.newKey = 'new';
            return json;
        });
    }).then(function(rs){
        console.log(rs); // jQ1.7.2 deferr不能嵌套(也就是不能在then里面再返回一个promise)  我这里jQ1.11是可以的
        // rs.then(function(data){});
        //报错 rs就是数据 不是一个promise
        //rs 就是上面嵌套的promise的resolve的值
    });


    //使用浏览器的Promsie (Chrome32+)=========================================================================
    function get(url) {
        // 返回一个新的 Promise
        return new Promise(function(resolve, reject) {
            // 经典 XHR 操作
            var req = new XMLHttpRequest();
            req.open('GET', url);

            req.onload = function() {
                // 当发生 404 等状况的时候调用此函数
                // 所以先检查状态码
                if (req.status == 200) {
                    // 以响应文本为结果,完成此 Promise
                    resolve(req.response);
                } else {
                    // 否则就以状态码为结果否定掉此 Promise
                    // (提供一个有意义的 Error 对象)
                    reject(Error(req.statusText));
                }
            };

            // 网络异常的处理方法
            req.onerror = function() {
                reject(Error("Network Error"));
            };

            // 发出请求
            req.send();
        });
    }
    var story = get('story.json');
    story.then(function(response) {
        console.log("Success!", response);
    }, function(error) {
        console.error("Failed!", error);
    }).then(function(res) {
        console.log(res); //前一个若没有返回值的话这里是undefined
    }, function(err) {
        console.log(err);
    });

    story = get('story.json');
    story.then(function(res){
        return JSON.parse(res);
    }).then(function(obj){
        console.log(obj);
    });
    //可以简写成
    story.then(JSON.parse).then(function(obj) {
        console.log(obj);
    });
    //这是为什么呢  虽然我们看不到JSON.parse的实现(在console中得到的结果是 function parse() { [native code] }  )
    //var xxx = JSON.parse(xxx)  说明这个函数接受一个参数且有返回值  所以可以猜测JSON.parse() 大致是 function(str){... retunn obj} 这个样子
    //和前面的完成写法就是一样的

    //再来一个setTimeout的例子
    //我把ajax的例子放在前面是因为我觉得 ajax的使用场景会更容易理解
    var getData = function(){
        var data;
        setTimeout(function(){
            data = 'data';
        },0);
        return data;
    }
    console.log(getData()); //undefined //显然这样是得不到结果的
    //所以我们必须传入一个回调函数
    var getData = function(callback){
        var data;
        setTimeout(function(){
            data = 'data';
            callback(data);
        },0);
    }
    getData(function(data){
        console.log(data)
    });
    //复杂了就不好办了
    // 所以可以这样
    var getData = function(){
        var promise = new Promise(function(resolve, reject){
            setTimeout(function(){
                resolve('data');
            },0);
        });
        return promise;
    }
    getData().then(function(data){
        console.log(data);
    });



    //链式操作 ===========================================================================================
    //Promise的嵌套=======(在then的函数中又返回一个Promise)===============================================
    get('story.json').then(function(data){
        return get('story.txt');
    }).then(function(rs){
        console.log(rs); //虽然前一个Promise返回的是一个Promise对象  但是这里的rs并不是一个Promise  而是前面的Promise对象resolve的结果 //也就是story.txt中的内容
    })


    function getJSON(url) {
        return get(url).then(JSON.parse); //这里返回的是一个promise  且resolve函数的返回值是JSON.parse()后的对象
    }

    var storyPromise;
    function getChapter(i) {
        storyPromise = getJSON('story.json');
        return storyPromise.then(function(story) { //story的值是 JSON.parse(story.json)
            return getJSON(story.chapterUrls[i]);
            //和上面一样 这里虽然又返回了一个新的Promise 但实际上
        });
    }
    function getChapter2(){
        // 上面一段相当于
        var temp1 = get('story.json');
        var temp2 = temp1.then(function(story){
            return JSON.parse(story);
        });
        var temp3 = temp2.then(function(story){
            return get(story.chapterUrls[i]).then(function(data){
                return JSON.parse(data);
            })
        })
        return temp3;  //return 的是一个promise 其resolve值又是一个promise  这个promise的resolve值才是对应的chapter的内容
    }


    getChapter(0).then(function(chapter) {
        console.log(chapter);
        return getChapter(1);  //就是chapter-2.json
    }).then(function(chapter) {
        console.log(chapter);
    });


    //将jQ的ajax变成标准的Promise ======================================================
    var fetchData = Promise.resolve($.get('story.txt')); //转化为promise对象  //有的是cast 至少Chrome中的Promise是没有cast这个方法的
    fetchData.then(function(result) {
        return JSON.parse(result);
    }).catch(function(error) {
        //handle error
    }).then(function(data){
        console.log(data);
    });


    //Promise 不会立即执行 它仍然是异步的===================================================
    var promise = new Promise(function(resolve, reject) {
        console.log(0);
        resolve(1);
        console.log(2);
    })
    console.log(3);
    promise.then(function(value) {
        console.log(value);
    })
    console.log(4);
    //输出结果是  0 2 3 4 1

    //Promise 语法糖
    Promise.resolve(1);
    //相当于
    new Promise(function(resolve) {
        resolve(1);
    })

    Promise.reject(2);
    //相当于
    new Promise(function(resolve, reject) {
        reject(2);
    })

    Promise.resolve(1).catch(onRejected);
    //相当于
    Promise.resolve(1).then(undefined, onRejected);

 

posted @ 2015-06-17 21:31  cart55free99  阅读(214)  评论(0编辑  收藏  举报