美文网首页
Promise学习总结

Promise学习总结

作者: 阿鲁提尔 | 来源:发表于2021-01-27 17:53 被阅读0次

    了解promise诞生的历史背景


    1.词语本意解释

    promise [ˈprɑ:mɪs] 许诺;允诺;(有可能)
    从字面意思,表示一个将来的状态。
    用在异步操作里面,帮我们去处理一件未来可能发生的一件什么事。

    2.MDN解释
    • promise对象用于异步计算
    • 一个promise表示一个现在、将来或永远不可能可用的值。
    3.按照用途来解释
    • 主要用来异步计算
    • 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果。
    • 可以在对象之间传递和操作promise,帮助我们处理队列。
    4.为什么会有Promise?
    • JavaScript包含大量异步操作
      • JavaScript为检查表单而生。
      • 创造它的首要目标是操作DOM
      • 所以,JavaScript的操作大多是异步的。
    5.为什么异步操作可以避免界面冻结呢?
    • 假设你去到一家饭店,自己找座坐下了,然后招呼服务员拿菜单。
    • 服务员说:“对不起,我是同步服务员,我要服务完这张桌子才能招呼你。”
    • 你是不是很想抽ta?
    • 那一桌人明明已经吃上了,你只是想要菜单,这么小的一个动作,服务员却要你等到别人的一个大动作完成。
    • 这就是同步的问题: 顺序交付的工作1234,必须按照1234的顺序完成。
    • 异步,则是将耗时很长的A交付的工作交给系统之后,就去继续做B交付的工作。等到系统完成前面的工作之后,再通过回调或者事件,继续做A剩下的工作。
    • 从观察者的角度看起来,AB工作的完成顺序,和交付他们的时间顺序无关,所以叫"异步"。
    6.异步操作的常见语法
    • 事件侦听与响应
    document.getElementById('start').addEventListener('click', start, false);
    
    function start() {
        // 响应事件,进行相应的操作
    }
    
    // jQuery 用 `.on()` 也是事件侦听
    $('#start').on('click', start);
    
    • 回调
    // 比较常见的有ajax
    $.ajax('http://baidu.com', {
        success: function (res) {
            // 这里就是回调函数了
        }
    });
    
    // 或者在页面加载完毕后回调
    $(function(){
        // 这里也是回调函数
    });
    
    7.浏览器中的JavaScript
    • 异步操作以事件为主,如ready、onload
    • 回调主要出现在Ajax和file API
      这个时候问题尚不算严重
    8.有了Node.js之后

    对异步的依赖进一步加剧了...
    Node.js出现了的时候,PHP、JAVA、Python这些服务器端的语言都已经很成熟了。Node.js作为一个后来者,想要从中分一杯羹,必须有自己的绝活。

    • 无阻塞高并发,是Node.js的招牌
    • 异步操作是其保障。
    • 大量操作依赖回调函数。
    9.使用Node.js开发时的问题
    • 不好维护
      稍有不慎,就会踏入“回调地狱”
    a(function (resultsFromA) {
        b(resultsFromA, function (resultsFromB) {
            c(resultsFromB, function (resultsFromC) {
                d(resultsFromC, function (resultsFromD) {
                    e(resultsFromD, function (resultsFromE) {
                        f(resultsFromE, function (resultsFromF) {
                            console.log(resultsFromF);
                        })
                    })
                })
            })
        })
    });
    
    • 除此之外,还有更深层次的问题
      遍历目录,找出最大的一个文件。
    这段代码跑在node环境中,使用一些node模块。
    const fs = require('fs');  //文件系统
    const path = require('path');
    
    function findLargest(dir, callback) {
        fs.readdir(dir, function (err, files) {
        //用fs.readdir读文件夹的内容。传入回调函数
            if (err) return callback(err); // [1]
            //如果发现错误,就用回调函数传出错误
    
            //如果读出来就执行下面操作
            let count = files.length; // [2]
            //取出来文件数量
            let errored = false;
            let stats = [];
            files.forEach( file => {  //对文件进行遍历
                fs.stat(path.join(dir, file), (err, stat) => {
                //每一个文件都用fs.stat去取状态。取出状态用到回调函数
                    if (errored) return; // [1]
                    //发生错误,中断,return掉
                    if (err) {
                        errored = true;
                        return callback(err);
                    }
                    stats.push(stat); // [2]
                    //没有发生错误,把stat文件放入数组
    
                    if (--count === 0) {  //用count变量来计数,每读完一个文件,都减一,当到0的时候,就认为所有文件都读完了
                        let largest = stats  //然后对数组进行遍历,找出其中
                            .filter(function (stat) { return stat.isFile(); })
                            .reduce(function (prev, next) {
                                if (prev.size > next.size) return prev;
                                //找出其中最大的文件信息,用下面的callback返回
                                return next;  //记下内容
                            });
                        callback(null, files[stats.indexOf(largest)]);
                        //第一个参数,是否有参数,因为是正常的,所以返回null
                    }
                });
            });
        });
    }
    
    findLargest('./path/to/dir', function (err, filename) {
    //使用的时候调用,'传入要查找的目录',传入回调函数
    //回调函数接受两个参数。“错误”,“文件名”
        if (err) return console.error(err);  
        //如果有错误,就返回错误信息。
        console.log('largest file was:', filename);
        //没有错误,返回文件名
    });
    //在标记的地方有问题,以后补充问题
    

    异步回调有四个问题

    • 嵌套层次很深,难以维护
    • 无法正常使用return 和 throw
    • 无法正常检索堆栈信息
    • 多个回调之间难以建立联系

    Promise入门

    1.Promise简介
    new Promise(
        /* 执行器 executor */
        function (resolve, reject) {
            // 一段耗时很长的异步操作
            resolve(); // 数据处理完成
            reject(); // 数据处理出错
        }
    )
        .then(function A() {
            // 成功,下一步
        }, function B() {
            // 失败,做相应处理
        });
    
    2.Promise详解
    • Promise是一个代理对象,它和原先要进行的操作并无关系。
    • 它通过引入一个回调,避免更多的回调。
    3.Promise有三个状态:
    • pending [待定] 初始状态
    • fulfilled [实现] 操作成功
    • rejected [被否决] 操作失败

    Promise状态发生改变,就会触发.then()里的响应函数处理后续步骤
    Promise状态一经改变,不会再变。


    4.范例
    • 定时执行
    console.log('here we go');
    new Promise( resolve => {
        setTimeout( () => {
            resolve('hello');
        }, 2000);
    })
        .then( value => {
            console.log( value + ' world');
        });
    
    //输出结果
    here we go
    hello world  //2秒之后输出
    
    5.两步执行范例
    • 分两次,顺序依次执行
    console.log('here we go');
    new Promise( resolve => {
        setTimeout( () => {
            resolve('hello');
        }, 2000);
    })
        .then( value => {
            console.log(value);
            return new Promise( resolve => {
                setTimeout( () => {
                    resolve('world');
                }, 2000);
            });
        })
        .then( value => {
            console.log( value + ' world');
        });
    
    //输出结果
    here we go
    hello  //2秒
    world world  //2秒
    
    6.已完成的Promise,再执行.then()
    console.log('start');
    
    let promise = new Promise(resolve => {
        setTimeout(() => {
            console.log('the promise fulfilled');
            resolve('hello, world');
        }, 1000);
    });
    
    setTimeout(() => {
        promise.then( value => {
            console.log(value);
        });
    }, 3000);
    
    //输出结果
    start
    the promise fulfilled  //1秒之后输出
    hello, world  //再过2秒之后输出
    
    7.在.then()的函数里面不返回新的Promise,会怎么样?
    console.log('here we go');
    new Promise(resolve => {
        setTimeout( () => {
            resolve('hello');
        }, 2000);
    })
        .then( value => {
            console.log(value);
            console.log('everyone');
            (function () {
                return new Promise(resolve => {
                    setTimeout(() => {
                        console.log('Mr.Laurence');
                        resolve('Merry Xmas');
                    }, 2000);
                });
            }());
            return false;  //没有等待里面的promise执行
            //但是里面的定时器仍在等待执行
            //在promise里面如果不直接返回一个promise实例
            //就会默认执行下一个环节
            //即使返回false也不影响下一组,false作为直接传递到下一组
        })
        .then( value => {
            console.log(value + ' world');
        });
    
    //输出结果
    here we go  //先输出
    
    hello  //这三个同时输出
    everyone
    false worl
    
    Mr.Laurence  //最后输出这个
    
    8.then()
    • .then()接受两个函数作为参数,分别代表fulfilled和rejected
    • .then() 返回一个新的Promise实例,所以它可以链式调用
    • 当前面的Promise状态改变时,.then()根据其最终状态,选择特定的状态响应函数执行。
    • 状态响应函数可以返回新的promise,或其他值
    • 如果返回新的Promise,那么下一级.then()会在新Promise状态改变之后执行。
    • 如果返回其他任何值,则会立刻执行下一级.then()
    
    

    小测试

    1. .then()里有.then()的情况
    • 因为.then()返回的还是Promise实例
    • 会等里面的.then()执行完,在执行外面的。
    • 对于我们来说,此时最好将其展开,会更好读。
    console.log('start');
    new Promise( resolve => {
        console.log('Step 1');
        setTimeout(() => {
            resolve(100);
        }, 1000);
    })
        .then( value => {
            return new Promise(resolve => {
                console.log('Step 1-1');
                setTimeout(() => {
                    resolve(110);
                }, 1000);
            })
                .then( value => {
                    console.log('Step 1-2');
                    return value;
                })
                .then( value => {
                    console.log('Step 1-3');
                    return value;
                });
        })
        .then(value => {
            console.log(value);
            console.log('Step 2');
        });
    
    //输出结果
    start
    Step 1
    
    Step 1-1
    Step 1-2
    Step 1-3
    
    Step 2
    

    学会使用promise解决异步回调带来的问题

    掌握promise的进阶用法

    相关文章

      网友评论

          本文标题:Promise学习总结

          本文链接:https://www.haomeiwen.com/subject/earccftx.html