javascript之promise | 青训营笔记

110 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第4天

  • Promise是JS中用于处理异步编程的新的解决方案(旧的解决方案是回调函数

异步操作

  1. fs文件操作

        require('fs').readFile('./index.html',(err,data)=>{})
    
  2. 数据库操作

  3. AJAX

        $.get('/server',(data)=>{})
    
  4. 定时器

        setTimeout((=>{},2000));
    

使用Promise的原因

  • Promise支持链式调用,可以解决回调地狱问题
    • 回调地狱:回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
    • 回调地狱导致代码不易阅读,且不方便异常处理
    • 使用Promise使得回调函数的方式更加灵活

promise用法

  • 流程:启动异步任务=>返回promise对象=>给promise对象绑定回调函数(甚至可以在异步任务结束后指定多个)

  • promise是一个构造函数,函数的参数是一个函数,内部包含异步操作。异步操作执行成功调用resolve方法,异步操作执行失败调用reject方法。resolve和reject方法在then方法中指定。

    const p=new Promise((resolve,reject)=>{
        setTimeout(()=>{
            let p=rand(1,100);
            if(p<30){
                resolve(p);//异步操作执行成功,可把promise状态设置为成功。函数类型的数据
            }else{
                reject(p);//异步操作执行失败,可把promise状态设置为失败。函数类型的数据
            }
        },1000);
    });
    //成功和失败时的回调,then方法
    p.then((value)=>{
        alert("恭喜中奖!,您的中奖码为"+value);//异步操作执行成功
    },(reason)=>{
        alert("未中奖,您的失败码为"+reason);//异步操作执行失败
    })
    
  • 用promise封装异步操作FS

    const fs=require("fs");
    //回调函数形式
    // fs.readFile("./test.txt",(err,data)=>{
    //     if(err) throw err;
    //     console.log(data.toString());
    // });
    //promise形式。
    const p=new Promise((resolve,reject)=>{
        fs.readFile("./test.txt",(err,data)=>{
            if(err) reject(err);
            resolve(data.toString());
        })
    });
    p.then((value)=>{
        console.log(value);
    },(reason)=>{
        console.log(reason);
    })
    
  • 用promise封装AJAX请求

     //使用Promise形式
    const p=new Promise((resolve,reject)=>{
        //1.创建对象
        const xhr=new XMLHttpRequest();
        //2. 初始化
        xhr.open("GET","https://api.apiopen.top/getJoke");
        //3. 发送数据
        xhr.send();
        //4. 处理响应结果
        xhr.onreadystatechange=function(){
            if(xhr.readyState==4){
                //判断响应码
                if(xhr.status>=200&&xhr.status<300){
                    //控制台输出响应体
                    resolve(xhr.response);
                }else{
                    //输出状态码
                    reject(xhr.status);
                }
            }
        }
    });
    p.then((value)=>{
        console.log(value);
    },(reason)=>{
        console.log(reason);
    });
    
  • 使用promise封装读取文件的操作

    /**
     * 函数myReadFile:使用promise方法封装了读取文件的操作
     * 参数:文件路径
     * 返回值:promise对象
     */
    function myReadFile(path){
        return new Promise((resolve,reject)=>{
            require("fs").readFile(path,(err,data)=>{
                if(err) reject(err);
                resolve(data.toString());
            });
        })
        
    }
    //这样就将异步操作转换为了同步操作
    myReadFile("./test.txt").then((value)=>{
        console.log(value);
    },(reason)=>{
        console.log(reason);
    });
    
  • 借助util的promisfy函数,将异步操作promise化

    /**
     * 借助util的promisfy函数,将异步操作函数promise化
     */
    const util=require("util");
    const fs=require("fs");
    ​
    const myReadFile=util.promisify(fs.readFile);
    myReadFile("./test.txt").then((value)=>{
        console.log(value.toString());
    },(reason)=>{
        console.log(reason)
    });
    

Promise对象的状态

  • pending:未决定的
  • resolved:已完成
  • rejected:失败

Promise对象的值

  • 实例对象中的另一个属性【PromiseResult】,保存着异步任务对象成功/失败的结果
  • resolve
  • reject

Promise的基本流程

promise流程.PNG

promise构造函数

Promise(executor){}
  • executor是构造函数的形参,是一个函数。称为执行器,通常写为(resolve,reject)=>{}
  • resolve函数:内部定义成功时调用的函数
  • reject函数:内部定义失败时,调用的函数
  • 注意:executor中的代码会在Promise内部立即同步执行。异步操作是在resolve中

then方法

    promiseObj.then(onResolved,onRejected)
  • then方法是处理回调函数,异步操作在这里执行
  • onResolved函数:执行成功的回调函数
  • onRejected函数:执行失败的回调函数
  • 返回一个新的promise对象

catch方法:失败的回调函数

    promiseOBJ.catch((reason)=>{})

async函数

  • 函数的返回值为promise对象
  • promise对象的结果由async函数执行的返回值决定

await函数

  • await右边的表达式为promise对象

  • 如果右边的表达式为promise对象,await返回的是promise成功的值

  • await必须写在async函数中。但async函数中可以没有await。

  • 如果await的promise失败了,就会抛出异常,通过try....catch捕获处理

     async function main(){
         let p=new Promise((resolve,reject)=>{
             reject('error');
         });
         //p成功时
         let res=await p;
         //p失败时
         try{
             let res=await p;
         }catch(e){
             console.log(e);
         }
     }

async和await函数的结合使用

  • await必须放在async函数中
   const util=require('util');
   const fs=require('fs');
   ​
   const myReadFile=util.promisify(fs.readFile);
   async function my(){
       let d1=await myReadFile('./test.txt');
       let d2=await myReadFile('./test02.txt');
       console.log(d1+d2);
   }
   my();