Promise语法,详细讲解(重难点)

176 阅读4分钟

1.Promise介绍

1.1什么是Promise

  • Promise是一个构造函数,用于创建Promise对象
    
  • Promise对象可以理解为是一个处理异步操作的容器
    

1.2Promise的作用

  • 解决回调地狱
    
  • 回调地狱: 异步回调,层层嵌套
    
/* 
为什么要学习Promise?

1.Promise作用 : 解决回调地狱问题
    回调地狱 : 异步回调 层层嵌套
*/

//需求: 依次读取 文件  a.txt , b.txt , c.txt 这三个文件内容
const fs = require('fs');

//(1)能直接按照顺序写吗?  : 不能,因为异步操作 是无序的
fs.readFile("./data/a.txt", 'utf-8', (err, data) => {
    if(err){
        console.log(err);
    }else{
        console.log(data);
    };
});

fs.readFile("./data/b.txt", 'utf-8', (err, data) => {
    if(err){
        console.log(err);
    }else{
        console.log(data);
    };
});

fs.readFile("./data/c.txt", 'utf-8', (err, data) => {
    if(err){
        console.log(err);
    }else{
        console.log(data);
    };
});


//(2)解决方案 : 在回调函数中嵌套执行
//弊端 : 形成回调地狱(异步回调 层层嵌套,非常麻烦且不便于维护)
//读取文件A
fs.readFile("./data/a.txt", 'utf-8', (err, data) => {
    if(err){
        console.log(err);
    }else{
        console.log(data);
        //A读取成功之后开始读取B
        fs.readFile("./data/b.txt", 'utf-8', (err, data) => {
            if(err){
                console.log(err);
            }else{
                console.log(data);
                //B读取成功之后开始读取C
                fs.readFile("./data/c.txt", 'utf-8', (err, data) => {
                    if(err){
                        console.log(err);
                    }else{
                        console.log(data);
                    }
                });
            }
        });
    }
});

2.Promise的基本使用

2.1.实例化Promise对象
  • 将异步代码放到Promise中
  • resolve 异步代码 正确状态
  • reject  异步代码失败状态(resolve和reject是回调函数)
new Promise((resolve,reject)=>{你的异步操作}) 
2.2. 调用then方法处理异步操作的结果
  •  Promise实例对象.then(res=>{处理成功结果},err=>{处理失败结果})
  •  或 Promise实例对象.then(res=>{处理成功结果}).catch(err=>{处理失败结果})
  推荐第二种写法
/* 
1.Promise是一个构造函数 , 返回一个Promise对象
2.使用流程
    (1)实例化Promise对象 : 将异步操作放入Promise中
    (2)调用then() 方法: 处理异步操作结果
*/

const fs = require('fs');
/** 1. 实例化Promise
* @description:实例化Promise
* @param {Function}  (resolve:成功处理函数,reject:失败处理函数)=>{ 异步操作代码 }
* @return: Promise对象
*/
 const p1 = new Promise((resolve,reject)=>{
     //读文件
     fs.readFile('./data/a.txt','utf8',(err,data)=>{
        if(err == null){ 
            /* 
            (1)异步操作成功,则执行 resolvce()
            (2)resolve会把把promise对象的状态从 pending进行中 改为 fulfilled成功
            (3)该方法本质是调用 then() 中的第一个方法
            */
            resolve(data);
        }else {
            /* 
            (1)异步操作失败,则执行 reject()
            (2)reject会把把promise对象的状态从 pending进行中 改为 rejected失败
            (3)该方法本质是调用 then() 中的第二个方法
            */
            reject(err); 
        }
     });
 });

 /* 2. p1.then() : 处理异步操作结果 */
 p1.then((data)=>{
    //成功了,打印文件数据
    console.log(data);
 },(err)=>{
    //失败了,打印错误信息
    console.log(err);
 });

3.Promise特点介绍(原理篇)

promise本质 `不是控制` 异步代码的`执行顺序`(无法控制) , `而是控制`异步代码结果`处理的顺序`
promise本身只是一个"容器",真正异步的是它的两个回调resolve()和reject()。

3.1.Promise对象有三个状态

a.pending(进行时)
b.fulfilled(已成功)
c.rejected(已失败)

3.2. Promise改变状态只有两种可能

a.pending变成fulilled
    *此时执行resolve
b.pending变成rejected
    *此时执行reject

3.3. Promise在创建对象的时候,里面的代码会立即执行

(1)不要在Promise里面处理异步结果
(2)而是将结果交给resolve和reject,然后让then()来处理异步结果   
总结: 不要在创建promise的时候去处理异步操作结果,而应该通过 then() 方法来处理  

3.4. promise解决回调地狱的原理

在promise的then方法中,返回下一个promise

总结: promise的本质不是控制异步代码的执行顺序(无法控制),而是控制异步代码处理结果的顺序。

const fs = require('fs');

//(1) 创建三个异步操作  promise

//读取文件A
const p1 = new Promise((resolve,reject)=>{
    //读文件
    fs.readFile('./data/a.txt','utf8',(err,data)=>{
       if(err == null){ 
            //成功
           resolve(data);
       }else {
           //失败
           reject(err); 
       }
    });
});

//读取文件B
const p2 = new Promise((resolve,reject)=>{
    //读文件
    fs.readFile('./data/b.txt','utf8',(err,data)=>{
       if(err == null){ 
            //成功
           resolve(data);
       }else {
           //失败
           reject(err); 
       }
    });
});

//读取文件C
const p3 = new Promise((resolve,reject)=>{
    //读文件
    fs.readFile('./data/c.txt','utf8',(err,data)=>{
       if(err == null){ 
            //成功
           resolve(data);
       }else {
           //失败
           reject(err); 
       }
    });
});

// (2)按照顺序处理异步操作结果
p1.then((data)=>{//第一个异步结果
    console.log(data);
    return p2;//返回下一个promise
}).then((data)=>{ // 第二个异步结果  (由于p1.then方法返回的是p2,而p2也有自己的then,所以可以继续调用p2的then方法)
    console.log(data);
    return p3;//返回下一个promise
}).then((data)=>{ // 第三个异步结果  
    console.log(data);
});

4. Promise解决回调地狱封装

const fs = require('fs');


//1.封装一个函数 :  根据文件名生成  文件读取的promise
function getPromise(fileName) {
    let p = new Promise((resolve, reject) => {
        //读文件
        fs.readFile(`./data/${fileName}.txt`,'utf-8', (err, data) => {
            if (err == null) {
                //成功
                resolve(data);
            } else {
                //失败
                reject(err);
            }
        });
    });
    return p;
};

//2.解决需求: 要先读a, 读完a后读b, 读完b后读c.

//开始读取a
getPromise('a').then((data)=>{
    console.log(data);
    //继续读取b
    return getPromise('b');
}).then((data)=>{
    console.log(data);
    //继续读取c
    return getPromise('c');
}).then((data)=>{
    console.log(data);
});//异步回调队列结束

5. Promise对象的all方法

● 作用: 将所以的Promise合成一个Promise
● 所以异步执行完毕才会执行then方法
● 参数是一个数组,数组里是每一个Promise实例对象[p1,p2,p3],处理后的结果也是数组中的顺序。

6. Promise对象的race方法

1. promise实例对象的race方法:将多个Promise合并成一个Promise
    * 任何一个异步  执行完毕就会执行then方法
2. 解决需求: a , b , c 任意一个成功