zoukankan      html  css  js  c++  java
  • JavaScript Promise学习笔记

    JavaScript Promise学习笔记

    Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。

    构造 Promise

    现在我们新建一个 Promise 对象:

    new Promise(function (resolve, reject) {
        // 要做的事情...
    });
    

    通过新建一个 Promise 对象好像并没有看出它怎样 "更加优雅地书写复杂的异步任务"。我们之前遇到的异步任务都是一次异步,如果需要多次调用异步函数呢?例如,如果我想分三次输出字符串,第一次间隔 1 秒,第二次间隔 4 秒,第三次间隔 3 秒:

    setTimeout(function () {
        console.log("First");
        setTimeout(function () {
            console.log("Second");
            setTimeout(function () {
                console.log("Third");
            }, 3000);
        }, 4000);
    }, 1000);
    

    现在我们用 Promise 来实现同样的功能:

    new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log("First");
            resolve();
        }, 1000);
    }).then(function () {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.log("Second");
                resolve();
            }, 4000);
        });
    }).then(function () {
        setTimeout(function () {
            console.log("Third");
        }, 3000);
    });
    

    Promise 构造函数只有一个参数,是一个函数,这个函数在构造之后会直接被异步运行,所以我们称之为起始函数。起始函数包含两个参数 resolve 和 reject。

    resolve 和 reject 都是函数,其中调用 resolve 代表一切正常,reject 是出现异常时所调用的

    当 Promise 被构造时,起始函数会被异步执行:

    new Promise(function (resolve, reject) {
        console.log("Run");
    });
    //这段程序会直接输出 Run。
    

    Promise 类有 .then() .catch() 和 .finally() 三个方法,这三个方法的参数都是一个函数,

    .then() 可以将参数中的函数添加到当前 Promise 的正常执行序列,

    .catch() 则是设定 Promise 的异常处理序列,

    .finally() 是在 Promise 执行的最后一定会执行的序列。

    .then() 传入的函数会按顺序依次执行,有任何异常都会直接跳到 catch 序列:

    new Promise(function (resolve, reject) {
        console.log(1111);
        resolve(2222);
    }).then(function (value) {
        console.log(value);
        return 3333;
    }).then(function (value) {
        console.log(value);
        throw "An error";
    }).catch(function (err) {
        console.log(err);
    });
    //1111
    //2222
    //3333
    //An error
    

    resolve() 中可以放置一个参数用于向下一个 then 传递一个值,then 中的函数也可以返回一个值传递给 then。但是,如果 then 中返回的是一个 Promise 对象,那么下一个 then 将相当于对这个返回的 Promise 进行操作,这一点从刚才的计时器的例子中可以看出来。

    reject() 参数中一般会传递一个异常给之后的 catch 函数用于处理异常。

    但是请注意以下两点:

    • resolve 和 reject 的作用域只有起始函数,不包括 then 以及其他序列;
    • resolve 和 reject 并不能够使起始函数停止运行,别忘了 return。

    Promise 函数

    上述的 "计时器" 程序看上去比函数瀑布还要长,所以我们可以将它的核心部分写成一个 Promise 函数:

    function print(delay, message) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.log(message);
                resolve();
            }, delay);
        });
    }
    

    然后我们就可以放心大胆的实现程序功能了:

    print(1000, "First").then(function () {
        return print(4000, "Second");
    }).then(function () {
        print(3000, "Third");
    });
    

    异步函数

    在 Promise 中我们编写过一个 Promise 函数:

    function print(delay, message) {
        return new Promise(function (resolve, reject) {
            setTimeout(function () {
                console.log(message);
                resolve();
            }, delay);
        });
    }
    

    然后用不同的时间间隔输出了三行文本:

    print(1000, "First").then(function () {
        return print(4000, "Second");
    }).then(function () {
        print(3000, "Third");
    });
    
    //我们可以将这段代码变得更好看:
    async function asyncFunc() {
        await print(1000, "First");
        await print(4000, "Second");
        await print(3000, "Third");
    }
    asyncFunc();
    

    异步函数 async function 中可以使用 await 指令,await 指令后必须跟着一个 Promise,异步函数会在这个 Promise 运行中暂停,直到其运行结束再继续运行。

    异步函数实际上原理与 Promise 原生 API 的机制是一模一样的,只不过更便于程序员阅读。

    处理异常的机制将用 try-catch 块实现:

    async function asyncFunc() {
        try {
            await new Promise(function (resolve, reject) {
                throw "Some error"; // 或者 reject("Some error")
            });
        } catch (err) {
            console.log(err);
            // 会输出 Some error
        }
    }
    asyncFunc();
    

    如果 Promise 有一个正常的返回值,await 语句也会返回它:

    sync function asyncFunc() {
        let value = await new Promise(
            function (resolve, reject) {
                resolve("Return value");
            }
        );
        console.log(value);
    }
    asyncFunc();
    输出:
    //Return value
    
  • 相关阅读:
    js去掉字符串前后空格三种方法及最佳方案
    javascript笔记:Date对象及操作方法
    高性能网站建设指南总结
    javascript之词法作用域及函数的运行过程
    LETTers比赛第四场N!
    LETTers比赛第三场 1003 大明A+B解题报告
    LETTers比赛第三场 1004 Max Sum Plus Plus 解题报告
    LETTers比赛第三场 1002 Ignatius and the Princess III解题报告
    LETTers第五场Sleeping 解题报告
    LETTers比赛第四场N!的最高位
  • 原文地址:https://www.cnblogs.com/yxyc/p/14642887.html
Copyright © 2011-2022 走看看