Promise and Asynchronous Programming
Because the execution engine is single-threaded, it needs to track the code that is about to run. That code is placed in a task queue. Whenever a piece of code is ready to execute, it is added to the task queue. Whenever a piece of code in the engine finishes execution, the event loop executes the next task in the queue.
Promise acts as a placeholder for the result of an asynchronous operation. It doesn't subscribe to an event, nor does it pass a callback function to the target function. Instead, it makes the function return a Promise, like this:
// readFile承诺在未来的某个刻完成
let promise = readFile('txx.txt')
Promise Lifecycle
- pending
- fulfilled (Success)
- rejected (Program error or some other reason)
The [[PromiseState]] internal property is used to represent the three states of a Promise. This property is not exposed on the Promise object, so the state of a Promise cannot be programmatically detected. Only when the Promise state changes can specific actions be taken via the then() method. Therefore, all Promises have a then method, which accepts two arguments: two callback functions for when it is fulfilled and when it is rejected.
If an object implements the then method mentioned above, we call that object a thenable object. All Promise objects are thenable objects, but not all thenable objects are Promises.
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){
// 拒绝
})
If a Promise is passed to the Promise.resolve() method or the Promise.reject() method, that Promise will be returned directly.
Rejection Handling in Node.js Environment
- 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'))
Chaining Promises and Chained Return Values
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"
})
Returning Promises in a Promise Chain
Promise.all()
It accepts only one argument and returns a Promise. This argument is an iterable object containing multiple monitored Promises. The returned Promise will only be resolved when all Promises in the iterable object are resolved, and it will only be fulfilled when all Promises in the iterable object are fulfilled. As long as one Promise is rejected, the returned Promise will be rejected without waiting for all others to complete.
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()
As long as one Promise resolves, there's no need to wait for all of them to complete. Once a Promise in the array is fulfilled, the Promise.race() method will also return a specific Promise, just like the Promise.all() method.
Promise Inheritance
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-based Asynchronous Task Execution
Refactoring the previous file reading functionality. As long as every asynchronous operation returns a Promise, this process can be greatly simplified and made usable. Using Promises as a common interface for all asynchronous code can simplify the task executor.
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://walker-learn.xyz/archives/4337