zoukankan      html  css  js  c++  java
  • 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);
  • 相关阅读:
    字符串_操作
    Error: Cannot find module 'webpack-cli/bin/config-yargs'
    ElementUI-Table 表头无法编辑问题
    ElementUI-Cascader组件同时支持懒加载和选择任意一级 问题踩坑
    vue强制刷新子组件
    footer部分,当页面主题内容不满一屏时,始终位于页面底部
    未知宽高的元素水平垂直居中方法总结
    fix元素居中
    link和@import引入css的区别
    Jquery拓展方法
  • 原文地址:https://www.cnblogs.com/cart55free99/p/4584421.html
Copyright © 2011-2022 走看看