Promise与异步编程
因为执行引擎是单线程的,所以需要跟踪即将运行的代码,那些代码被放在一个任务队列中,每当一段代码准备执行时,都会被添加到任务队列中,每当引擎中的一段代码结束执行,事件循环会执行队列中的一下个任务。
Promise
相当于异步操作结果占位符,它不会去订阅一个事件,也不会传递一个回调函数给目标函数,而是让函数返回一个Promise,就像这样
// readFile承诺在未来的某个刻完成
let promise = readFile('txx.txt')
Promise的生命周期
- pending
- fulfilled 成功
- rejected 程序错误或一些其他原因
[[PromiseState]]
内部属性被用来表示Promise的3种状态,这个属性不暴露在Promise对象上,所以不能以编程的方式检测Promise的状态,只有当Promise状态改变时,通过then()方法来采取特定的行为。所以Promise都有then方法,它接受两个参数,fulfilled和rejected时的两个回调函数
如果一个对象实现了上述的then方法,那这个对象我们就称之为thenable对象,所有的Promise对象都是thenable对象,但并非所有thenable对象都是Promise。
let promise = readFile("example.txt");
promise.then(function(contents){
// 完成
},function(err){
// 拒绝
})
promise.then(function(contents){
// 完成
})
promise.then(null,function(err){
// 拒绝
})
// catch等同于上面这种
promise.catch(function(err){
// 拒绝
})
如果向Promise.resolve()方法或Promise.reject()方法传入一个Promise,那么这个Promise会被直接返回
Nodejs环境的拒绝处理
- unhandledRejection
- rejectionHandled
let rejected;
process.on("unhandledRejection",function(reason,promise){
console.log(reason.message); // "Explosin"
console.log(rejected === promise); // "Explosin"
})
rejected = Promise.reject(new Error('Explosin'))
串联Promise及链式返回值
let p1 = new Promise(function(resolve,reject){
resolve(42)
})
p1.then(function(value){
console.log(value)
return value+1;
})
.then(function(value){
console.log(value); // "43"
})
let p1 = new Promise(function(resolve,reject){
reject(42)
})
p1.catch(function(value){
console.log(value) // 42
return value+1;
})
.then(function(value){
console.log(value); // "43"
})
在Promsie链返回Promise
Promise.all()
只接受一个参数并返回一个Promise,该参数是一个含有多个受监视Promise的可迭代对象,只有当可迭代对象中所有Promise都被解决后返回的Promise才会被解决,只有当可迭代对象中所有Promise都完成后返回的promise才会被完成。只要有一个reject,就不用等所有的都完成就会被reject。
let p1 = new Promise(function(resolve,reject){
resolve(42)
})
let p2 = new Promise(function(resolve,reject){
reject(43)
})
let p3 = new Promise(function(resolve,reject){
resolve(44)
})
let p4 = Promise.all([p1,p2,p3])
p4.catch(function(value){
console.log(Array.isArray(value)); //false
console.log(value); // 43
})
Promise.race()
只要有一个resolve,不用等所有的都被完成。一旦数组中的某个Promise被完成,Promise.race()方法也会像Promise.all()方法一样返回一个特定的Promise
Promise继承
class MyPromise extends Promise {
// 使用默认的构造函数
success(resolove,reject){
return this.then(resolove,reject)
}
failure(reject){
return this.catch(reject)
}
}
let promise = new MyPromise(function(resolve,reject){
resolve(42)
})
promise.success(function(value){
console.log(value) // 42
})
.failure(function(value){
console.log(value)
})
基于Promise的异步任务执行
改造之前的文件读取功能。只要每个异步操作都返回Promise,就可以极大地简化并能用化这个过程。以Promise作为通用接口用于所有异步代码可以简化任务执行器。
let fs = require("fs");
function run(taskDef){
// 创建迭代器
let task = taskDef()
// 开始执行任务
let result = task.next();
// 递归函数遍历
(function step(){
// 如果有更多任务要做
if(!result.done){
// 用一个Promise来解决会简化问题
let promise = Promise.resolove(result.value);
promise.then(function(value){
result = task.next(value);
step()
})
.catch(function(error){
result = task.throw(error);
step();
})
}
}())
}
// 定义一个可用于任务执行器的函数
function readFile(filename){
return new Promise(function(resolove,reject){
fs.readFile(filename,function(err,contents){
if(err){
reject(err);
} else {
resolove(contents)
}
})
})
}
// 执行一个任务
run(function *(){
let contents = yield readFile("config.json");
doSomethingWith(contents);
console.log("Done")
})
主题测试文章,只做测试使用。发布者:Walker,转转请注明出处:https://joyjs.cn/archives/4337