ES6之Promise

1.异步编程的背景知识

JavaScript引擎是基于单线程时间循环的概念构建的,同一时刻只允许一个代码块在执行。当多个代码块同时访问并改变状态的时候,程序很难维护并保证状态不会出错。
因此引入了回调函数来改进异步编程模型。

2.回调模式

异步代码都会在未来的某个时间点执行。

const fs = require('fs');
fs.readFile("example.txt", function(err, contents){
	if(err){
    console.log(err)	;
	}
	console.log(contents);
})
console.log('Hi')

上述代码中,readFile()函数读取磁盘上的example.txt文件(第一个参数),读取完毕后执行回调函数(第二个参数),如果出现错误,错误对象被赋值给回调函数的err参数,如果正常,将会以字符串的形式被赋值给contents参数。
执行结果:
ES6之Promise_第1张图片
代码的执行过程,调用readFile()函数后,console.log(‘Hi’)语句立即执行并输出“Hi”,当readFile()结束执行时,会向任务队列的末尾添加一个新的任务(该任务包含回调函数以及相应的参数),当队列前面所有的任务都完成后才执行该任务,并最终执行console.log(contents);输出所有内容。

回调模式可以来链接多个调用

const fs = require('fs');
fs.readFile("example.txt", function(err, contents){
	if(err){
    console.log(err)
  }
  fs.writeFile("example.txt",function(err, contents){
    if(err){
      console.log(err);
    }
    console.log("File was written");
  })
})
console.log('Hi')

但是如果回调次数过多的话,会使代码缩进增加,陷入了回调地狱。当需要追踪多个回调函数并进行操作的时候,Promise就能很好的改进这种情况

2.Promise
1.Promise的生命周期

Promise的三种状态

  • 进行中(pending)
  • 已完成(fulfilled)
  • 已拒绝(rejected)
  1. Promise的起始状态时是进行中,执行成功会变成已完成,执行失败则会变成已拒绝。
  2. 在后面两种情况下可以添加程序,以便于当Promise被解决时做出相应的操作,通过then()方法可以添加处理完成程序或者拒绝程序,通过catch()方法只能添加拒绝处理程序。
2.创建Promise

用Promise构造函数可以创建新的Promise

const p = new Promise(function(resolve,reject){
			//失败
			if(err){
				reject(error)
			}
			//成功
			resolve(value);
		})

构造函数接收一个参数,该参数又包含两个参数分别为resolve()函数和reject()函数,
resolve()函数在异步操作成功时调用,并将异步操作的结果作为参数传递出去,
reject()函数在异步操作失败时调用,并将异步操作错误信息作为参数传递出去。
实例创建成功后可以调用then()方法分别为reject和resolve状态添加回调函数

p.then(value=>{	
	//成功
      console.log(value);
    },reason=>{
    //失败
      console.(reason);
    })

Promise的执行器会立即执行,然后才执行后续流程的代码,例如:

const p = new Promise(function(reslove, reject){
  console.log('Promise')
  resolve()
})
console.log('Hi');

ES6之Promise_第2张图片
调用resolve()函数后会触发一个异步操作,传入then()和catch()方法的函数会被添加到任务队列中并异步执行。例如:

const p = new Promise(function(resolve, reject){
  console.log('Promise')
  resolve()
})
p.then(function(){
  console.log('Resolve');
})
console.log('Hi');

ES6之Promise_第3张图片
注意即使代码then()调用位于console.log(‘Hi’)之前,但其与执行器不同,它没有立即执行,这是因为,完成处理程序和拒绝处理程序总是在执行器完成之后被添加到任务队列的末尾。

3.串联的Promise

每次调用then()方法或者catch()方法,实际上创建并返回了另外一个Promise,只有当第一个Promise完成或者被拒绝后,第二个才会被解决,例如:

const p1 = new Promise(function(resolve, reject){
  resolve(42)
})
p1.then(function(value){
  console.log(value)
}).then(function(){
  console.log('Finished');
})

ES6之Promise_第4张图片
调用p1.then()后返回第二个Promise,紧接着又调用了他的then()方法。只有当一个个解决之后才会调用第二个的then方法完成处理程序。相当于下列代码:

const p1 = new Promise(function(resolve, reject){
  resolve(42)
})
const p2 = p1.then(function(value){
  console.log(value)
})
p2.then(function(){
  console.log('Finished');
})
4.链式调用Promise
const p1 = new Promise(function(resolve, reject){
  resolve(42)
})
p1.then(function(value){
  //第一个完成处理程序
  console.log(value);
  // 创建一个新的Promise
  let p2 = new Promise(function(resolve, reject){
  // 第二个完成处理程序
    resolve(43);
  })
  return p2;
}).then(function(value){
  console.log(value);
})

在p1的完成处理程序中创建了一个新的Promise,直到p2被完成才会执行第二个完成处理程序。

5.使用Promise封装读取文件
// 1.引入fs模块
const fs = require('fs');
// 2.调用方法,读取文件
// fs.readFile('./resources/test.md',(err,data)=>{
//   //如果失败,则抛出错误
//   if(err) throw err;
//   // 如果没有出错,则输出内容
//   console.log(data.toString());

// })
// 3. 使用promise封装
const p = new Promise(function(resolve,reject){
  fs.readFile('./resources/test.md',(err,data)=>{
    // 如果失败
    if(err) reject(err);
    // 如果成功
    resolve(data);
  })
}) 
p.then(function(value){
  console.log(value.toString());
},function(reason){
  console.log('读取失败')
})

6.使用Promise读取封装多个文件
// 引入fs 
const fs = require("fs");
// 回调实现
// const { resolve } = require("path");
// fs.readFile('./resources/test.md',(err,data1)=>{
//   fs.readFile('./resources/test1.md',(err,data2)=>{
//     fs.readFile('./resources/test2.md',(err,data3)=>{
//       let result = data1 +'\r\n' +data2 +'\r\n' + data3;
//       console.log(result);
//     })
//   })
// }) 
// 使用promise实现
const p = new Promise((resolve,reject)=>{
  fs.readFile('./resources/test.md',(err,data)=>{
    resolve(data);
  })
});
p.then(value=>{
  return new Promise((resolve,reject)=>{
    fs.readFile('./resources/test1.md',(err,data)=>{
      // value是第一个文件内容 data是第二个文件内容
      resolve([value,data])
    })
  })
}).then(value=>{
  return new Promise((resolve,reject)=>{
    fs.readFile('./resources/test2.md',(err,data)=>{
      // 压入
      value.push(data);
      resolve(value);
    })
  })
}).then(value=>{
  // 数据都保存在数组中,使用join方法进行数组拼接
  console.log(value.join('\r\n'));
})

你可能感兴趣的:(ES6)