黑马Nodejs笔记03 Promise

回调地狱的产生

无法保证顺序的代码:

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

fs.readFile('./data/b.txt', 'utf8', function (err, data) {
    if (err) {
      throw err
    }
    console.log(data)
})
            
fs.readFile('./data/c.txt', 'utf8', function (err, data) {
      if (err) {
        throw err
      }
      console.log(data)
})

由于是readFile是异步的,无法保证读取文件内容的输出是一步一步来的

如何保证顺序呢?通过回调的方式保证其顺序

var fs = require('fs')

fs.readFile('./data/a.txt', 'utf8', function (err, data) {
  if (err) {
    throw err
  }
  console.log(data)
  fs.readFile('./data/b.txt', 'utf8', function (err, data) {
    if (err) {
      throw err
    }
    console.log(data)
    fs.readFile('./data/c.txt', 'utf8', function (err, data) {
      if (err) {
        throw err
      }
      console.log(data)
    })
  })
})

这里只有三个异步函数,如果多个,会产生回调地狱。

一个任务依赖于一个异步任务执行完之后,这里必须进行嵌套才能解决。

问题:嵌套的太深,代码不好看,很难维护

怎么去解决这个问题呢?在ES6中新增了一个API——Promise

Promise是如何解决回调地狱的

promise是一个容器,里面存放了一个正在执行的任务(pending:正在执行),这个任务执行结束后,可能有两个状态,resolved(完成)和 rejected(失败),状态只能是其中的一种

promoise的使用

promise是一个构造函数

//promise容器一旦创建,就开始执行里面的代码,容器里可以放置异步函数,但是promise本身不是异步的

//创建Promise容器,给别人一个承若:I Promise you
var p1 =  new Promise(function(resolve,reject){
    console.log('hello') //这里的代码不是异步的
    fs.readFile('./data/a.txt','utf8',function(err,data){
        if(err){
            //承渃容器中的任务失败了,把容器的Pending状态变为 Rejected
        	//调用reject就相当于调用了then方法的第二个参数
            reject(err)
        }else{
            //承渃容器中的任务成功了,把容器的Pending状态变为 Resolved
            //调用resolve就相当于调用了then方法的第一个参数
            resolve(data)
        }
    })
})

//p1就是那个承若,当p1成功了,然后then做指定的操作,then方法接收的第一个function就是容器中的resolved函数
p1
  .then(function(data){
    console.log(data)
},function(err){
    console.log('读取文件失败了',err)
})

promise解决回调地狱问题示例

var p1 =  new Promise(function(resolve,reject){
    fs.readFile('./data/a.txt','utf8',function(err,data){
        if(err){
            reject(err)
        }else{
            resolve(data)
        }
    })
})

var p2 =  new Promise(function(resolve,reject){
    fs.readFile('./data/b.txt','utf8',function(err,data){
        if(err){
            reject(err)
        }else{
            resolve(data)
        }
    })
})

var p2 =  new Promise(function(resolve,reject){
    fs.readFile('./data/c.txt','utf8',function(err,data){
        if(err){
            reject(err)
        }else{
            resolve(data)
        }
    })
})

p1
  .then(function (data) {
    console.log(data)
    //当p1读取成功的时候
    //当前函数中的return的结果就可以在后面的then中function
    //当你return 123 后面接接收到 123
    //	  return 'hello' 后面就接收到 ’hello'
    //	  没有return后面收到的就是undefined
    //上面那些return的数据没什么卵用
    //真正有用的是:我们可以return一个promise对象
    //当return一个Promise对象的时候,后续的then中的方法的第一个参数会作为p2的resolve
    return p2
  }, function (err) {
    console.log('读取文件失败了', err)
  })
  .then(function (data) {
    console.log(data)
    return p3
  })
  .then(function (data) {
    console.log(data)
    console.log('end')
  })

封装promise ——API

var fs = require('fs')

function pReadFile(filePath) {
  return new Promise(function (resolve, reject) {
    fs.readFile(filePath, 'utf8', function (err, data) {
      if (err) {
        reject(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)
  })

简单封装Promise版本的ajax方法

function pGet(url){
    return new Promise(function(resolve,reject){
        var xhr = new XMLHttpRequest()
        xhr.onLoad = function(){
            resolve(xhr.responseText)
        }
        xhr.onerror = function(err){
            reject(err)
        }
        xhr.open('get',url,true)
        xhr.send()
    })
}

pGet('http:127.0.0.1/user')
	.then(function(data){
    	console.log(data)
    return pGet('http://127.0.0.1/job')
	})
	.then(function(data){
		console.log(data)          
	})

Moogoose里所有的封装的函数都可以使用promise

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章