创建一个 readFile.js,读取三个文件abc的内容并输出到控制台

var fs = require('fs')
fs.readFile('./a.txt','utf-8',function (err,data) {
if(err)
throw err //js语法,抛出异常,阻止程序执行,把错误打印到控制台
console.log(data) //将a.txt内容输出到控制台
}) fs.readFile('./b.txt','utf-8',function (err,data) {
if(err)
throw err
console.log(data)
}) fs.readFile('./c.txt','utf-8',function (err,data) {
if(err)
throw err
console.log(data)
})

一般来说文件内容少的会先输出,但不一定,由于读取文件是异步操作,所以无法保证abc的输出顺序

若想abc按顺序输出,就需要将代码嵌套

var fs = require('fs')
fs.readFile('./a.txt','utf-8',function (err,data) {
if(err)
throw err
console.log(data) //打印a.txt后再去读取b.txt
fs.readFile('./b.txt','utf-8',function (err,data) {
if(err)
throw err
console.log(data) //打印b.txt后再去读取c.txt
fs.readFile('./c.txt','utf-8',function (err,data) {
if(err)
throw err
console.log(data)
})
})
})

像这样,在异步编程中,形成了回调函数嵌套,嵌套过多时被称为回调地狱(callback hell),此方式虽然能让异步操作按顺序执行,但十分不利于阅读和维护

为了解决回调地狱嵌套编码方式带来的问题,ES6 新增了一个 API 叫 Promise,是一个构造函数

Promise上有两个函数叫resolve(成功后的回调函数)和reject(失败后的回调函数)

Promise原型里有一个then方法,所以只要是Promise创建的实例都可访问then方法

Promise 容器存在一个异步任务,任务只有三种状态:Pending 为正在执行,Resolve 为已解决,Reiected 为失败

示例

var fs = require('fs')
//Promise容器一旦创建就开始执行里面的代码
var p = new Promise(function (resolve,reject) {
  fs.readFile('./a.txt','utf-8',function (err,data) {
  if(err){
  reject(err) //把容器的Pending状态变为Rejected
}else{
resolve(data) //把容器的Pending状态改为Resolve
}
})
}) //如何获取容器成功和失败的数据,就要用到p实例对象的then方法
//then方法接收的第一个function就是容器中的resolved,第二个function是reject
//两个function的参数就是上面容器resolve和reject传来的data和err.若resolve(123),则这里data就是123
p.then(function (data) {
  console.log(data)
},function (err) {
consoel.log('文件读取失败',err)
})

Promise容器的创建不是异步的,但内部往往传入异步任务

封装 Promise 版本的 readFile.js

var fs = require('fs')
function readFile(filePath) {
//将Promise实例对象返回
return new Promise(function (resolve,reject) {
fs.readFile(filePath,'utf-8',function (err,data) {
if(err){
reject(err)
}else{
resolve(data)
}
})
})
} //因为返回的都是Promise的实例对象,所以可链式调用then
readFile('./a.txt')
.then(function (data) {
console.log(data) //data就是上面resolve传来的a文件的内容
//然后将新的数据(err和data)通过resolve和reject传递给下一个then的function
return readFile('./b.txt')
})
.then(function (data) {
console.log(data)
return readFile('./c.txt')
})
.then(function (data) {
console.log(data)
})

封装 Promise 版本的 ajax 方法

function get(url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest()
xhr.open('get', url)
xhr.send()
xhr.onload = function () {
resolve(xhr.responseText) //成功则把获取的数据放resolve这个回调函数中
}
xhr.onerror = function (err) {
reject(err) //失败则把失败信息放reject里
}
})
} get('./a.txt')
.then(function (data) {
console.log(data)
return get('./b.txt')
})
.then(function (data) {
console.log(data)
return get('./c.txt')
})
.then(function (data) {
console.log(data)
})

如果前面的promise执行失败,不想让后续的promise操作被终止,可为每个promise指定失败的回调,然后在失败回调里return新的promise

如果后续的promise执行依赖于前面的,前面的失败了,则后面的没有继续执行下去的意义时,可捕获异常

get('./a.txt')
.then(function (data) {
console.log(data)
return get('./b.txt')
})
.then(function (data) {
console.log(data)
return get('./c.txt')
})
.then(function (data) {
console.log(data)
})
.catch(function(err){ //上面不要写失败回调
console.log(err.message)
})

如果前面有任何的promise执行失败则会立即终止所有promise执行并立刻进入catch中

这就是捕获异常的两种方式,根据需求,可选择失败回调或catch

模拟 jQuery 的 get 方法

jq中的ajax()返回的是Promise实例,所以可直接点then()

既能使用 Promise 也可以使用回调函数嵌套的方式,只需加多一个回调函数即可

function get(url,callback) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest()
xhr.open('get', url)
xhr.send()
xhr.onload = function () {
callback(xhr.responseText)
resolve(xhr.responseText) //成功则把获取的数据放resolve这个回调函数中
}
xhr.onerror = function (err) {
callback(err)
reject(err) //失败则把失败信息放reject里
}
})
} /*get('./a.txt')
.then(function (data) {
console.log(data)
return get('./b.txt')
})
.then(function (data) {
console.log(data)
return get('./c.txt')
})
.then(function (data) {
console.log(data)
})*/ get('./a.txt',function (data) {
console.log(data)
get('./b.txt',function (data) {
console.log(data)
get('./c.txt',function (data) {
console.log(data)
})
})
})

浏览器、Node、mongoose所有 API 都支持 Promise

最新文章

  1. PHP_php.ini_说明详解
  2. LeetCode127:Word Ladder II
  3. 如何写一个c++插件化系统
  4. Linux rsync 同步实践
  5. C#消息模拟
  6. Linux使用wake_up_interruptible()唤醒注册到等待队列上的进程
  7. bzoj2127: happiness
  8. 百度Clouda的初步探索
  9. DBSNMP和SYSMAN用户初始密码及正确的修改方式
  10. sql权限报表小知识
  11. makefile使用.lds链接脚本以及 $@ ,$^, $,< 解析
  12. hdu 4778 Gems Fight! 状态压缩DP
  13. F01:金融学第一定律:时间的价值
  14. Semaphore 源码分析
  15. 信用卡欺诈数据的分析-excel篇
  16. SaltStack快速入门-配置管理
  17. XML Namespace (xmlns) 属性
  18. Linux命令之cp
  19. stylus笔记
  20. templates的语法

热门文章

  1. (链表) 206. Reverse Linked List
  2. Mac iOS Mac Watch 应用和游戏编程开发工具推荐
  3. Shiro中session超时页面跳转的处理
  4. oracle数据库的简单操作
  5. ThreadPoolExecutor线程池详解
  6. 7.桥接模式(Bridge Pattern)
  7. CSS3笔记4
  8. bzoj千题计划318:bzoj1396: 识别子串(后缀自动机 + 线段树)
  9. bzoj千题计划308:bzoj4589: Hard Nim(倍增FWT+生成函数)
  10. vue项目中引用jquery