Promise 、asyns、await介绍

回调地狱(callback hell)

回调地狱概念图: javascript

回调地狱:在咱们须要对一个异步操做进行频繁的调用的时候,且要保证一步操做的顺序,可能会出现.java

var fs=require('fs');

/* 注意这里的fs.readFile是一个异步任务,因此这里他们输出的顺序并非 按照代码的书写顺序,他们读取文件的输出顺序,跟文件资源的大小还有其余的元素有很大的关系 */

fs.readFile('./data/a.txt','utf8',function(err,data){
    if(err){
        /* 抛出异常 1.阻止程序的执行 2.把错误的消息打印到控制台 */
      throw err  
    }
    console.log(data);
});

fs.readFile('./data/b.txt','utf8',function(err,data){
    if(err){
       /* 抛出异常 1.阻止程序的执行 2.把错误的消息打印到控制台 */
      throw err  
    }
    console.log(data);
});


fs.readFile('./data/c.txt','utf8',function(err,data){
    if(err){
       /* 抛出异常 1.阻止程序的执行 2.把错误的消息打印到控制台 */
      throw err  
    }
    console.log(data);
});
复制代码

经过回调嵌套的方式保证顺序:ajax

var fs = require('fs');

/* 注意这里的fs.readFile是一个异步任务,因此这里他们输出的顺序并非 按照代码的书写顺序,他们读取文件的输出顺序,跟文件资源的大小还有其余的元素有很大的关系 */

fs.readFile('./data/a.txt', 'utf8', function (err, data) {
    if (err) {
        /* 抛出异常 1.阻止程序的执行 2.把错误的消息打印到控制台 */
        throw err
    }
    console.log(data);
    fs.readFile('./data/b.txt', 'utf8', function (err, data) {
        if (err) {
            /* 抛出异常 1.阻止程序的执行 2.把错误的消息打印到控制台 */
            throw err
        }
        console.log(data);

        fs.readFile('./data/c.txt', 'utf8', function (err, data) {
            if (err) {
                /* 抛出异常 1.阻止程序的执行 2.把错误的消息打印到控制台 */
                throw err
            }
            console.log(data);
        });
    });
});

复制代码

回调地狱的缺点: 1)代码的可维护性很是差,不利于代码的阅读 2)层层嵌套,代码复杂.promise

Promise简介

为了解决以上编码方式带来的问题(回调地狱嵌套),因此在ECMAScript 6 中新增了一个API:promise Promise的英文就是承诺 保证的意思bash

概念 : Promise是ES6中的新语法,Promise是一个构造函数,每一个new 出来的Promis实例对象都表明一个异步操做.异步

注意:使用promise并不会减小代码量
复制代码

Promise概念图:

Promise语法介绍

简单建立:async

//  Promise是构造函数
//  Promise.prototype上有.then() .catch .finally(),由于他绑定到了原型上,因此根据原型链的查找规则,他的实例对象也可使用这个方法
// Promise表示异步操做

// 下面的这个代码表示建立了一个形式上的异步操做

// 经过new Promise()的时候,提供了一个function函数,在function函数中,能够执行具体的异步操做
const p=new Promise(function(){
    // 在这个function中能够执行具体的异步操做
    // 好比读文件,或发送ajax
    // fs.readFile()
})
复制代码

.then方法的使用:函数

const fs=require('fs');
// 在ES6中新增了一个API Promise
// Promise 是一个构造函数

// 建立promise容器
// 1.给别人一个承诺
// Promise容器一旦建立,就开始执行里面的代码,
// 承诺自己不是异步的,可是内部每每都是封装一个异步任务
var p1=new Promise(function(resolve,rejected){
    fs.readFile('./data/a.txt','utf8',function(err,data){
        if(err){
            // 失败了,承诺容器中的任务失败了
            // console.log(err);
            // 把容器的Pending状态改变为Rejected
            //调用reject就至关于调用了then方法的第二个参数 
            rejected(err);
        }else{
            // 承诺容器中的任务成功了
            // console.log(data);
            // 把容器的Pending状态改成Resolved
             // 也就是说这里调用的resolve方法实际上就是then方法传递的function
            resolve(data);
        }
    });
});

// p1就是那个承诺
// 当p1成功了而后(then)作指定的操做
// then方法接收的function就是容器中的resolve
p1.then(function(data){
    console.log(data);
},function(err){
    console.log('读取文件失败了...',err);
})
复制代码

封装Promise版本的ReadFile:

const fs = require('fs');
 function pReadFile(filePath){
     return new Promise(function (resolve, rejected) {
        fs.readFile('./data/a.txt', 'utf8', function (err, data) {
            if (err) {
                rejected(err);
            } else {
                resolve(data);
            }
        });
    });
 }
 pReadFile('./data/a.txt')
    .then(function(data){
        console.log(data);
        return pReadFile('./data/b.txt');
    })
    .then(function(data){
        console.log(data);
        return pReadFile('./data/c.txt');
    })
    .then(function(data){
        console.log(data);
    })
    //能够经过.catch方法,捕获前面全部的.then方法发生的错误,几种处理
    .catch(function(err){
        console.log(err.message)
    })
复制代码

Promise代码图示:优化

asyns、await对Promise的优化

Generator

  • 说到async函数就不得不提起他在ES6中的表现,他其实就是Generator函数的一种语法糖
  • Generator能够理解为一个状态机,他身上挂载了好多的状态,
  • 执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,仍是一个遍历器对象生成函数。返回的遍历器对象,能够依次遍历 Generator 函数内部的每个状态。

形式上,Generator 函数是一个普通函数,可是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不一样的内部状态(yield在英语里的意思就是“产出”) ES7 中的 async 和 await 能够简化 Promise 调用,提升 Promise 代码的 阅读性 和 理解性;ui

// 若是某个方法内部用到了await关键字,那么这个方法必须被修饰为异步async方法
// await只能用在被async修饰的方法中
async function test(){
    // 若是某个方法的返回值是Promise的实例对象,就能够用await修饰Promise实例
    // await只能用在被async修饰的方法中
  const data=await getContentPath('./files/1.txt').catch(err=>err);
  if(data instanceof Error){
      console.log('文件读取失败')
  }else{
      console.log(data);
  }
  console.log(data);
  const data2=await getContentPath('./files/2.txt');
  console.log(data2);
  const data3=await getContentPath('./files/3.txt');
  console.log(data3);
}

// 这是异步方法,可是并非纯粹的异步方法
// 在异步方法中,遇到第一个await以前,全部的代码都是同步执行的
test();

复制代码
注意:async和await通常是同步使用的,二者缺一不可,
复制代码
相关文章
相关标签/搜索