美文网首页ES6
ES6基本的语法(十三) Promise

ES6基本的语法(十三) Promise

作者: StevenTang | 来源:发表于2021-03-10 00:18 被阅读0次

    Promise

    Promise 是一个对象,它代表了一个异步操作的最终完成或者失败。因为大多数人仅仅是使用已创建的 Promise 实例对象,所以本教程将首先说明怎样使用 Promise,再说明如何创建 Promise。
    本质上 Promise 是一个函数返回的对象,我们可以在它上面绑定回调函数,这样我们就不需要在一开始把回调函数作为参数传入这个函数了。

    一个 Promise 必然处于以下几种状态之一:

    • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
    • 已兑现(fulfilled): 意味着操作成功完成。
    • 已拒绝(rejected): 意味着操作失败。

    待定状态的 Promise 对象要么会通过一个值被兑现(fulfilled),要么会通过一个原因(错误)被拒绝(rejected)。当这些情况之一发生时,我们用 promise 的 then 方法排列起来的相关处理程序就会被调用。如果 promise 在一个相应的处理程序被绑定时就已经被兑现或被拒绝了,那么这个处理程序就会被调用,因此在完成异步操作和绑定处理方法之间不会存在竞争状态。

    基本使用

    // Promise
    // 需要传递一个执行期函数 executor function
    let Op = new Promise(()=>{
    
    });
    

    Promise 和里面的函数是同步执行

    // Promise
    // 需要传递一个执行期函数 executor function
    let Op = new Promise(()=>{
        // 里面的函数和 Promis 是同步执行
      console.log('0')
    });
    console.log('1')
    
    // 先打印 0
    // 后打印 1
    

    从上面的例子中我们就知道 Promise 和里面的函数是同步执行

    异步操作

    // Promise
    // 需要传递一个执行期函数 executor function
    // 可以传递参数 resolve, reject 分来用来触发成功和失败的回调
    // 使用 setTimeout 模拟异步操作
    let op = new Promise((resolve, reject)=>{
        // 异步操作
      setTimeout(()=>{
            Math.random() * 100 > 60 ? resolve("ok"):reject('no')
      },1000)
    });
    // 异步执行
    op.then((val)=>{
        console.log(val); // 输出ok
    },(err)=>{
        console.log(err); // 输出no
    })
    

    在上面的代码中我们使用 setTimeout 来模拟一个异步请求,在 Promise 中有两个参数 resolvereject 分别用来触发成功和失败的回调。

    // Promise
    // 需要传递一个执行期函数 executor function
    // 可以传递参数 resolve, reject 分来用来触发成功和失败的回调
    let op = new Promise((resolve, reject)=>{
        console.log(0)
      resolve(1);
    });
    // 异步执行
    op.then((val)=>{
        console.log(val); // 输出ok
    },(err)=>{
        console.log(err);// 输出on
    })
    console.log(2);
    
    // 输出 0 2 1
    

    是因为 .then 是异步执行,被当成微任务。在上面我们也讲了 resolvereject 分别用来触发成功和失败的回调函数。

    // Promise
    // 需要传递一个执行期函数 executor function
    // 可以传递参数 resolve, reject 分来用来触发成功和失败的回调
    setTimeout(()=>{
            console.log('setTime');
      },0)
    let op = new Promise((resolve, reject)=>{
        console.log(0)
      resolve(1);
    });
    // 异步执行
    //
    op.then((val)=>{
        console.log(val); // 输出ok
    },(err)=>{
        console.log(err);// 输出on
    })
    console.log(2);
    
    // 输出 0 2 1 setTime
    

    我们都知道在 JavaScript 的任务队列中分为宏任务和微任务,我们通过 setTimeout() 或者触发事件、时间处理函数、ajax的回调都是放在宏任务。宏任务会被优先放到任务队列(task queue)里面去 ,微任务会被后被放入任务对列之中,但是微任务有优先执行权,所以微任务会优先被执行。

    Promise 的链式操作

    // Promise
    // 需要传递一个执行期函数 executor function
    // 可以传递参数 resolve, reject 分来用来触发成功和失败的回调
    // 使用 setTimeout 模拟异步操作
    let op = new Promise((resolve, reject)=>{
        // 异步操作
      setTimeout(()=>{
            Math.random() * 100 > 60 ? resolve("ok"):reject('no')
      },1000)
    });
    // 异步执行
    op.then((val)=>{
        console.log(val); // 输出ok
    },(err)=>{
        console.log(err); // 输出no
    }).then((val)=>{
        console.log("ok then2"+val); // 输出ok
    },(err)=>{
        console.log("no then2"+err); // 输出no
    })
    
    // 不管前面是输出的 ok 还是 no 都会输出 ok then2 undefined
    // 前面的代码不抛出错误, 下面的都会输出 ok then2 undefined
    

    在上面的代码中,不管是成功还是失败,都会输出 ok then2 undefined,除非前面的代码抛出错误

    // Promise
    // 需要传递一个执行期函数 executor function
    // 可以传递参数 resolve, reject 分来用来触发成功和失败的回调
    // 使用 setTimeout 模拟异步操作
    let op = new Promise((resolve, reject)=>{
        // 异步操作
      setTimeout(()=>{
            Math.random() * 100 > 60 ? resolve("ok"):reject('no')
      },1000)
    });
    // 异步执行
    op.then((val)=>{
        console.log(val); // 输出ok
      return 20
    },(err)=>{
        console.log(err); // 输出no
      return 30
    }).then((val)=>{
        console.log("ok then2"+val); // 输出ok
    },(err)=>{
        console.log("no then2"+err); // 输出no
    })
    
    // 不管前面是输出的 ok 还是 no 都会输出 ok then2 20
    // 前面的代码不抛出错误, 下面的都会输出 ok then2 20
    // 如果抛出错误,这会输出 ok then2 30
    

    上面的代码中加入了一个 return 20/30 会成为后面链式调用的参数,返回值会成为下一个 then 注册函数的执行参数。

    如果返回的是一个 Promise 对象

    // Promise
    // 需要传递一个执行期函数 executor function
    // 可以传递参数 resolve, reject 分来用来触发成功和失败的回调
    // 使用 setTimeout 模拟异步操作
    let op = new Promise((resolve, reject)=>{
        // 异步操作
      setTimeout(()=>{
            Math.random() * 100 > 60 ? resolve("ok"):reject('no')
      },1000)
    });
    // 异步执行
    op.then((val)=>{
        console.log(val); // 输出ok
      return new Pormise((resolve,reject)=>{
        resolve('newPromise, ok')/reject('newPromise, no')
      })
    },(err)=>{
        console.log(err); // 输出no
      return 30
    }).then((val)=>{
        console.log("ok then2"+val); // 输出ok
    },(err)=>{
        console.log("no then2"+err); // 输出no
    })
    
    // 不管前面是输出的 ok 还是 no 都会输出 ok then2 newPromise, ok
    
    // 如果抛出错误,这会输出 ok then2 newPromise, no
    

    下面的 .then 的执行结果会就根据第一个 .then 的结果去显示对应的内容,成功显示 ok then2 newPromise, ok,失败显示 ok then2 newPromise, no

    处理回调地狱

    let fs = require('fs');
    
    function readFile(path){
        return new Promise((resolve, reject)=>{
        fs.readFile(path,'utf-8',(err,data)=>{
            if(data){
            resolve(data);
          }
        })
      })
    }
    
    readFile(path).then((data)=>{
        return readFile(data);
    }).then((data)=>{
        return readFile(data);
    }).then((data)=>{
        conosle.log(data);
    })
    
    

    相关文章

      网友评论

        本文标题:ES6基本的语法(十三) Promise

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