1.js中完成异编程的方法
- 回调函数
- 事件监听
- 发布订阅
- Promise对象
当多个回调的执行是需要按照一定顺序的时候,回调函数的方式需要进行多层嵌套。所以采用Promise的链试调用来解决这个问题
2.Generator函数实现协成
使用yield作为暂停标记
3.generator的数据交换和错误处理
使用next(argument)传参数,使用throw()进行异常or错误处理。
4.使用generator封装异步操作
var fetch = require('node-fetch');
function* gen(){
var url = 'https://api.github.com/users/github';
var result = yield fetch(url);
console.log(result.bio);
}
代码执行的方式:
var g = gen();
var result = g.next();
result.value.then(function(data){
return data.json();
}).then(function(data){
g.next(data);
});
问题:流程管理比较麻烦,即何时执行第一阶段,何时执行第二阶段。
5.什么是Thunk函数
Thunk函数实现“传名调用”,将参数放到一个临时函数之中,再将这个临时函数传入函数体。这个临时函数就叫做 Thunk 函数。
js中的Thunk函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数,且只接受回调函数作为参数
// 正常版本的readFile(多参数版本)
fs.readFile(fn, argument,callback);
// ES6版本
const Thunk = function(fn) {
return function (...args) {
return function (callback) {
return fn.call(this, ...args, callback);
}
};
};
//函数调用方式
var readFileThunk = Thunk(fs.readFile);
readFileThunk(fileA)(callback);
//相当于fn(, , ,)变为fn()()();
6.generator函数的流程管理
-
使用whil循环进行自动流程管理
function* gen() {
}var g = gen(); var res = g.next(); while(!res.done){ console.log(res.value); res = g.next(); }
注意:不适合在异步操作中。因为不会判断何时异步操作会完成。处理方法:基于promise完成。即yield后面是promise对象。自启动也是基于promise的then()调用完成。
使用Thunk函数,Thunk函数在回调函数中将执行权交还给generator函数
-
异步操作流程管理,函数的手动执行方式
var fs = require('fs'); var thunkify = require('thunkify'); var readFileThunk = thunkify(fs.readFile); var gen = function* (){ var r1 = yield readFileThunk('/etc/fstab'); console.log(r1.toString()); var r2 = yield readFileThunk('/etc/shells'); console.log(r2.toString()); };
手动方式:回调函数中调用g.next()将执行权返回给generator函数
var g = gen();
var r1 = g.next();
r1.value(function (err, data) {
if (err) throw err;
var r2 = g.next(data);
r2.value(function (err, data) {
if (err) throw err;
g.next(data);
});
});
Thunk函数的自动流程管理(不太懂)
-
基于Promise的自启动
var fs = require('fs'); var readFile = function (fileName){ return new Promise(function (resolve, reject){ fs.readFile(fileName, function(error, data){ if (error) return reject(error); resolve(data); }); }); }; var gen = function* (){ var f1 = yield readFile('/etc/fstab'); var f2 = yield readFile('/etc/shells'); console.log(f1.toString()); console.log(f2.toString()); };
手动方式:
var g = gen();
g.next().value.then(function(data){
g.next(data).value.then(function(data){
g.next(data);
});
});
自动方式:
function run(gen){
var g = gen();
function next(data){
var result = g.next(data);
if (result.done) return result.value;
result.value.then(function(data){
next(data);
});
}
next();
}
run(gen);