美文网首页
【Nodejs笔记】nodejs入门简介_Promise(1)

【Nodejs笔记】nodejs入门简介_Promise(1)

作者: 李明燮 | 来源:发表于2022-06-01 09:28 被阅读0次

    1.Promiose 是什么?

    Promise是JS中进行异步编程的解决方案。可以有效的避免了之前版本的回调地狱方式。
    Promise是一个构造函数。
    Promise对象用来封装一个异步操作并可以获取成功或失败的结果值。

    简单的看看Promise和传统的回调方式:

    /*
        编写一个抽奖程序,抽奖的过程是:  
        取一个随机数1~100,1~30为中奖,31~100为没中奖。  
    */
    function rand(m, n) {
        return Math.ceil(Math.random() * (n - m + 1) + m - 1);
    }
    console.log('-----------传统方式-----------');
    {
        function raffle() {
            setTimeout(() => {
                let a = rand(1, 100);
                if (a < 30) {
                    console.log(`${a} | 恭喜你中奖了, 奖金是10万元。`);
                } else {
                    console.log(`${a} | 很遗憾,您没中奖,再接再厉!`);
                }
            }, 1000);
        }
    
        raffle();
    }
    
    console.log('-----------Promise方式-----------');
    {
        //new Promise的时候需要制定一个回调函数,这个函数的参数是resolve和reject。
        //resolve是成功时调用,reject是失败时调用。
        const p = new Promise((resolve, reject) => {
            setTimeout(() => {
                let a = rand(1, 100);
                if (a < 30) {
                    resolve(a);
                } else {
                    reject(a);
                }
            }, 1000);
        });
    
        //then也有2个回调函数,成功第一个,失败第二个。
        p.then((value) => {
            console.log(`${value} | 恭喜你中奖了, 奖金是10万元。`);
        }, (reason) => {
            console.log(`${reason} | 很遗憾,您没中奖,再接再厉!`)
        });
    }
    

    2.什么时候用Promise?

    简单的说异步编程的时候会使用Promise。
    一般的异步编程有: 1.fs文件读取 2.http请求 3.DataBase操作 4.定时器等等...

    下面我们看看简单的读取文件的方法:

    const fs = require('fs');
    
    //普通的回调函数的方式
    fs.readFile('./test.txt', (err, data) => {
        if (err) throw err;
        console.log(data.toString());
    });
    
    //promise的方式
    const p = new Promise(function (resolve, reject) {
        fs.readFile('./test.txt', (err, data) => {
            if (err) reject(err);
            resolve(data);
        });
    });
    
    p.then(function (value) {
        console.log(value.toString());
    }, function (reason) {
        console.log(reason);
    });
    

    这么一看Promise方式的代码好像更复杂....^^;;
    我们看看Promise的有点是什么?

    3.Promise优点

    1. 指定回调函数方式更加灵活。
      以前必须写在回调函数里面
      现在可以启动任务,返回Promise对象,然后给promise对象绑定回调函数。

    2. 支持链式调用,可以解决回调地狱
      以前的回调地狱,现在可以把回调函数放在Promise对象的then方法里面。

    第一个有点可能没什么太大的感触,但是回调地狱是没有Promise的链式调用之前是每个开发者的噩梦。
    我们举一个简单的例子看看:

    const fs = require('fs');
    
    /*
        想读取 test1.txt test2.txt test3.txt 三个文件,并且把它们的内容都读取出来。
        普通的回调方式,很容易就会发生回调地狱,如果有4个甚至更多文件,这个地狱就更深了...^^;;
    */
    
    //普通读取文件
    fs.readFile('./test1.txt', (err, data1) => {
        if (err) {
            console.log(err);
        } else {
            fs.readFile('./test2.txt', (err, data2) => {
                if (err) {
                    console.log(err);
                } else {
                    fs.readFile('./test3.txt', (err, data3) => {
                        if (err) {
                            console.log(err);
                        } else {
                            let result = data1 + '\r\n' + data2 + '\r\n' + data3;
                            console.log(result);
                        }
                    });
                }
            });
        }
    });
    
    
    //使用Promise读取文件, 虽然看着比普通的方式更复杂,
    //但是他解决的回调地狱的问题,以及提高了代码可读性。
    const p = new Promise(function (resolve, reject) {
        fs.readFile('./test1.txt', (err, data) => {
            if (err) reject(err);
            resolve(data);
        });
    });
    
    p.then(function (value) {
        return new Promise((resolve, reject) => {
            fs.readFile('./test2.txt', (err, data) => {
                if (err) reject(err);
                resolve([value, data]);
            });
        });
    }, function (reason) {
        console.log(reason);
    }).then(function (value) {
        return new Promise((resolve, reject) => {
            fs.readFile('./test3.txt', (err, data) => {
                if (err) reject(err);
                value.push(data);
                resolve(value);
            });
        });
    }, function (reason) {
        console.log(reason);
    }).then((value) => {
        console.log(value.join('\r\n'));
    });
    
    

    4.PromiseState

    Promise对象的状态有两种:pending和fulfilled。
    1.Pending: 等待中
    2.Resolved(fulfilled): 成功
    3.Rejected: 失败

    Pending: 等待中 => Resolved: 成功
    Pending: 等待中 => Rejected: 失败

    Resolved 方法里 throw 也可以把Promise状态改成 失败

    5.PromiseResult

    Promise 对象值 Promiseresult
    保存异步任务成功或失败的结果值
    resovle, reject 两个方法能修改这个值

    <!DOCType html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title></title>
    
        <script>
            const p = new Promise((resolve, reject) => { });
            console.log(p); 
            /*
                [[Prototype]]: Promise
                [[PromiseState]]: "pending"
                [[PromiseResult]]: undefined
            */
    
            const p1 = new Promise((resolve, reject) => {
                resolve('OK');
            });
            console.log(p1); //Promise {<fulfilled>: 'OK'}
            /*
                [[Prototype]]: Promise
                [[PromiseState]]: "fulfilled"
                [[PromiseResult]]: "OK"
            */
    
            const p2 = new Promise((resolve, reject) => {
                reject('fail');
            });
            console.log(p2);
            /*
                [[Prototype]]: Promise
                [[PromiseState]]: "rejected"
                [[PromiseResult]]: "fail"
            */
            
            const p3 = new Promise((resolve, reject) => {
                    throw ("fail");
            });
            console.log(p3);
            /*
                [[Prototype]]: Promise
                [[PromiseState]]: "rejected"
                [[PromiseResult]]: "fail"
            */
                
        </script>
    </head>
    
    <body>
    </body>
    
    </html>
    

    6.Promise API

    构造函数 Promise(executor)

    (resolve, reject) => {
    //这里的函数是同步调用的,不会进队列
    }
    then(onFulfilled, onRejected) //指定回调,成功的话执行前面的方法,失败执行后面的方法
    catch(onRejected) //执行失败时,调用的方法。
    finally(onFinally) //无论成功失败,都会执行。

    //如果传递参数是非Promise对象,返回结果为成功的的Promise对象,如果是参数是Promise对象,则看Promise本身的状态。
    let p1 = Promise.resolve(111);
    console.log(p1);

    //返回失败的Promise对象,无论是成功的Promise对象也是返回失败的Promise对象。
    let p2 = Promise.reject(222);
    console.log(p2);

    Promise.all

    //成功返回成功Promise数组对象,失败返回其中失败Promise对象
    const result = Promise.all(p1,p2,p3);
    console.log(result);

    Promise.race

    //谁先改变状态,返回他的Promise结果
    //成功返回成功Promise数组对象,失败返回其中失败Promise对象
    const result = Promise.all(p1,p2,p3);
    console.log(result);

    util.promisify

    const util = require('util');
    const fs = require('fs');
    
    //使用promisify返回一个新的函数
    let myReadFile = util.promisify(fs.readFile);
    
    myReadFile('./aa.txt').then(value=>{
        console.log(value.toString());
    }, reason=>{
        console.log(reason);
    })
    

    7.附加整理

    Promise 调用

    let p = new Promise((resolve, reject) => {
        setTimeout(()=> {
            resolve('OK');
        },2000)
    })
    
    p.then(value => {
        console.log(value);
    }, reason => {
        console.log(reason);
    }).then(value =>{
        return new Promise(()=>{});
    }).then(value =>{
        console.log('111');
    }).catch(err =>{
        console.warn(err);
    });
    

    自定义读取文件方法

    function myReadFile(path){
        return new Promise((resolve, reject)=>{
            require('fs').readFile(path, (err,data)=>{
                if(err) reject(err);
                resolve(data);
            });
        })
    }
    
    myReadFile('./test.txt')
    .then(value=>{
        console.log(value.toString());
    }, reason=>{
        console.log(reason);
    }) 
    

    欢迎大家的意见和交流

    email: li_mingxie@163.com

    相关文章

      网友评论

          本文标题:【Nodejs笔记】nodejs入门简介_Promise(1)

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