什么是异步/同步调用
异步调用就是你 喊 你朋友吃饭 ,你朋友说知道了 ,待会忙完去找你 ,你就去做别的了。
同步调用就是你 喊 你朋友吃饭 ,你朋友在忙 ,你就一直在那等,等你朋友忙完了 ,你们一起去。
异步不支持try/catch,try/catch只针对同步代码
- Callbackcallback就是在回调函数,在函数中会作为参数来实现:
let fs = require('fs'); // readFilefs.readFile('./2.promise/1.txt','utf8',function(err,data){ // error-first fs.readFile(data,'utf8',function(err,data){ // error-first console.log(data); });});// 并行 无法在同一时刻合并两节异步的结果,异步方案不支持returnfs.readFile('./2.promise/1.txt','utf8',function(err,data){ // error-first});fs.readFile('./2.promise/2.txt','utf8',function(err,data){ // error-first console.log(data);});复制代码
高阶函数
函数可以作为参数或者函数还可以作为返回值
1)批量生成函数
function isType(type){ // 偏函数 return function(content){ return Object.prototype.toString.call(content) === `[object ${type}]`; }}let isString = isType('String');let isArray = isType('Array');console.log(isArray('hello'));复制代码
2)预置函数作为参数 loadsh _.after
function after(times,callback){ return function(){ if(--times === 0){ callback(); } }}let eat = after(3,function(){ console.log('饱了')})eat();eat();eat();复制代码
2. Promise
callback虽然也能解决问题,但是要是多个函数嵌套的话不仅不好看难以维护,还会形成回调地狱。这个时候promise就出来啦!
let promise = new Promise(function (resolve,reject) { resolve(100)})//链式调用的特点,将第一次成功的返回值当成下一次回调函数的参数let p2 = promise.then(function (data) { return new Promise(function (resolve,reject) { resolve(data) })},function () {})p2.then().then().then(function (data) { console.log(data);},function(err){ console.log(err)})复制代码
promise 解决了回调地狱的问题,还解决了同步异步的返回结果,按照顺序执行
3. generator + co(Promise)
是由tj 写的一个自动迭代的库。generator函数要用*来标识,yield(暂停,产出),它将函数分割成很多块,用next来往下执行,返回结果是一个迭代器,yield后面跟着的是value值,yield等号前面的是我们当前调用next传进来的,但是第一次传进来是无效的:
function* read() { console.log(1); let a = yield '珠峰'; console.log(a); let b = yield 9 console.log(b); return b;}let it = read();console.log(it.next('213')); // {value:'珠峰',done:false}console.log(it.next('100')); // {value:9,done:false}console.log(it.next('200')); // {value:200,done:true}console.log(it.next('200')); // {value:200,done:true}复制代码
看co的源码就会发现co()执行返回的是一个new Promise:
// 异步 generator主要和promise搭配使用let bluebird = require('bluebird');let fs = require('fs');let read = bluebird.promisify(fs.readFile);//promisify可以转化成promisefunction* r() { let content1 = yield read('./2.promise/1.txt', 'utf8'); let content2 = yield read(content1, 'utf8'); return content2;}// co库 npm install co 可以自动的将generator进行迭代// let co = require('co');function co(it) { return new Promise(function (resolve, reject) { function next(d) { let { value, done } = it.next(d); if (!done) { value.then(function (data) { // 2,txt next(data) }, reject) } else { resolve(value); } } next(); });}co(r()).then(function (data) { console.log(data)})// generator原理是将一个函数划分成若干个小函数,没次调用时移动指针,内部是一个条件判断,走对应的逻辑// it.next().value.then(function(data){ // 2.txt// it.next(data).value.then(function(data){// console.log(it.next(data).value);// });// })复制代码
这里有一个插件就是bluebird,它有个promisify的方法,是可以将参数promise化。另外他的promisifyAll方法是将一个方法下面的函数转化成promise。:
let fs = require('fs');let bluebird = require('bluebird');function promisify(fn) { // promise化 将回调函数在内部进行处理 return function (...args) { return new Promise(function (resolve, reject) { fn(...args, function (err, data) { if (err) reject(err); resolve(data); }) }) }}function promisifyAll(obj) { Object.keys(obj).forEach(key => { // es5将对象转化成数组的方法 if (typeof obj[key] === 'function') { obj[key + 'Async'] = promisify(obj[key]) } })}promisifyAll(fs); // 将所有的方法全部增加一个promise化fs.readFileAsync('./2.promise/1.txt', 'utf8').then(function (data) { console.log(data);});复制代码
4.async await
号称异步调用的终极解决方案,成功解决了回调地狱,并发执行异步,在同一时刻同步返回结果,Promise.all,解决返回值问题,可以实现try,catch.
let bluebird = require('bluebird');let fs = require('fs');let read = bluebird.promisify(fs.readFile);// 用async 来修饰函数,aysnc需要配await,await只能promise// async和await(语法糖) === co + generatorasync function r(){ try{ let content1 = await read('./2.promise/100.txt','utf8'); let content2 = await read(content1,'utf8'); return content2; }catch(e){ // 如果出错会catch console.log('err',e) }}// async函数返回的是promise,r().then(function(data){ console.log('flag',data);},function(err){})复制代码