浅谈异步调用几种方式

什么是异步/同步调用

异步调用就是你 喊 你朋友吃饭 ,你朋友说知道了 ,待会忙完去找你 ,你就去做别的了。
同步调用就是你 喊 你朋友吃饭 ,你朋友在忙 ,你就一直在那等,等你朋友忙完了 ,你们一起去。
异步不支持try/catch,try/catch只针对同步代码
  1. Callback
    callback就是在回调函数,在函数中会作为参数来实现:
let fs = require('fs'); // readFile

fs.readFile('./2.promise/1.txt','utf8',function(err,data){ // error-first
    fs.readFile(data,'utf8',function(err,data){ // error-first
        console.log(data);
    });
});
// 并行 无法在同一时刻合并两节异步的结果,异步方案不支持return
fs.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)

co 是由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可以转化成promise

function* 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 + generator
async 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){

})



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值