概念
所谓Promise简单来说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上来说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。
捕获错误
如果不设置回调函数,Promise内部抛出的错误不会反应到外部,所以才有catch方法或者用then第二个回调函数都可以捕获Promise内部错误。还有一种情况是在Promise函数体外抛出的,会冒泡到最外层,成了未捕获的错误,会被浏览器打印出来。需要注意的是,catch方法返回的还是一个Promise对象,因此后面还可以接着调用then方法。
Promise.all()
Promise.all方法用于将多个Promise实例包装成一个新的Promise实例。
let p = Promise.all([p1, p2, p3])
p1,p2,p3都是Promise实例,如果不是就会调用Promise.resolve()方法,将参数转为Promise实例,再做进一步处理。Promise.all的参数是数组或具有Iterator接口的数据。
Promise由来
Promise是为了解决回调函数嵌套问题而提出的。它不是新的语法功能,而是一种新的写法,允许将回调函数的嵌套改写成链式调用。假定读取多个文件,普通回调函数写法如下:
fs.readFile(fileA, function (err, data) {
fs.readFile(fileB, function (err, data) {
// ...
})
})
Promise写法:
let readFile = require('fs-readFile-promise')
readFile(fileA).then(function (data) {
console.log(data.toString())
})
.then(function () {
return readFile(fileB)
})
.then(function (data) {
console.log(data.toString())
})
.catch(function(err) {
console.log(err)
})
上面代码已经把回调函数改成了直线执行的形式,但是加入了大量Promise的语法。Generator函数可以进一步改善代码运行流程。
Generator写法:
function * longTask (value1) {
try {
let value2 = yield step1(value1)
let value3 = yield step2(value2)
} catch (e) {
// ....
}
}
scheduler (longTask(initiaValue))
function scheduler (task) {
let taskObj = task.next(task.value)
// 如果未结束,就继续调用
if (!taskObj.done) {
task.value = taskObj.value
scheduler (task)
}
}
以上是Generator函数同步写法,如果用异步写法需要用Thunk函数,Thunk函数是自动执行Generator函数的一种方法。co模块是在Thunk函数基础上进一步优化自动执行Generator函数的一种方法。
Iterator接口为不同的数据结构提供了统一的访问机制,Generator函数是一种具有Iterator接口的数据。所以它才需要调用next()方法才能返回里面的元素。
不管是Promise、Generator函数、async函数都是为了优化回调函数,回调函数是用来解决异步请求后台的问题,异步是为了解决页面卡顿的问题,js执行机制。
异步---回调函数----Promise---Generator函数---async函数
看一下js执行机制,Event Loop,然后一步一步延伸。
async函数是Generator函数的语法糖。
网友评论