2019-10-30Node.js异步编程

1.1同步API,异步API

当中的API:有的通过返回值拿到结果,有的通过函数返回值方式拿到结果。
例如:

// 返回值拿到
// 路径拼接
const public = path.join(__dirname,'public');
// 请求地址解析
const urlObj = url.parse(req.url);
// 函数返回值
// 读取文件
fs.readFile('./demo.txt,'utf8',(err,result)=>{
         console.log(result);
});

为什么会有这两种方式?
===============================.
什么是同步API?
只有当前API执行完成后,才能继续执行下一个API
例如:

console.log('before');
console.log('after');
// 只有第一个执行完,才能执行第二个。这就是同步API,代码从上到下一行一行的执行,只有上一行代码执行完成,才能执行下一行代码。

什么是异步API?
当前API的执行,不会阻塞后面代码的执行!
例如:

console.log('before');
setTimeout(
()=>{console.log('last');
},2000)
console.log('after');
// 结果:先输出before,再输出after,2s后输出了last,(PS:虽然定时器代码在after前面,但是程序在执行到定时器代码时,并没有等待定时器代码执行完成,再执行after这个方法,在当前代码中定时器就是异步API,程序不需要等待异步API执行完成之后,再继续执行后面的代码,也就是说异步API不会阻塞后续代码的执行。)

在Node.js中异步API无处不在,掌握异步异步API,异步编程非常重要。

1.2同步API,异步API的区别(获取返回值)

同步API可以从返回值中拿到API执行的结果,但是异步API不可以。
例子:

// 同步
function sum (n1 ,n2){
         return n1 + n2;
}
const result =  sum(10,20);

// 异步
function getMsg(){
    setTimeout(function(){
         return{msg:'Hello Node,js'}
    },2000);
    //return undefined
}
const msg = getMsg();
console.log(msg);      

思考:是否能拿到函数返回值?

执行后返回: undefind

PS: 原因:当使用函数名getMsg函数名去调用getMsg()函数时,由于异步API不会阻塞代码的执行,所以在函数的底部直接return undefind(PS:因为没有写return,所以他默认返回的就是undefined,然后再过2秒后,他在setTimeout函数内部返回了一个对象,此时返回值早已拿到了undefined,然后直接进行了输出)

结论:在异步API中,无法通过返回值的方式去拿到异步API的执行结果。

1.3回调函数

那么异步API的返回值到底该怎么拿到?
实际上是通过回调函数拿到的,什么是回调函数,实际上就是自己定义函数,让别人去调用函数(看下面例子))

// getData函数定义
function getData(callback){}
//getData函数调用
getData(()=>{});
// callback仅仅是形参的名字,那么这个形参对应的实参实际上是一个函数,将一个函数作为另外一个函数的参数(没有问题),callback就是一个回调函数,在调用getData的时候传递了一个匿名函数(函数的定义,实际上这个函数在getData方法的内部调用,根据实际的情况决定是否要调用,来决定什么是要调用,这个参数就是回到函数)。

在代码编辑器中新建一个文件callback.js

function getData(callback){
    callback();
}
getData(function(){
    console.log('callback函数被调用了')
});

命令行工具执行node callback.js

返回:callback函数被调用了
// 这就是回调函数其中一种表现形式

函数写成这个样子有什么用?

function getData(callback){
    callback('123');              // 给callback传递参数 123
}
getData(function(n){          // 在这个函数里拿到123这个实参,使用形参n对象这个实参
    console.log('callback函数被调用了')
    console.log(n);
});

返回:callback函数被调用了
123

PS:123被输出了。如果getData这个函数在内部有异步操作,在异步操作执行完成之后,就可以调用callback('123')这个回调函数,并且把异步API执行的结果通过参数的形式传递给callback,那么我们在getData里面的回调函数里面就能够拿到异步API执行的结果。

回到第一个例子:

function getMsg(callback){
    setTimeout(function(){
       callback({
            msg:'hello node.js'
    }) 
    },2000);
}
getMsg(function(data){
  console.log(data);
});    

命令行执行

返回:{mag:'hello node.js'}
PS:通过回调函数的方式拿到了异步API执行的结果。

1.4同步API,异步API的区别(代码执行顺序)

同步API从上到下一次执行,前面代码没有执行完成之前,后面的代码不能执行

for(var i=0;i<100000;i++){
console.log(i);
}
console.log('for循环后面的代码');

PS:先执行for循环10万次,在for循环没有执行完成之前,后面的console.log()是不能执行的。

异步API不会等待API执行完成后再向下执行

console.log('代码开始执行');
setTiomeout(()=>{console.log('2S后执行的代码')},2000);
setTiomeout(()=>{console.log('0S后执行的代码')},0);
console.log('代码结束执行');

返回:代码开始执行
代码结束执行
0S后执行的代码
2S后执行的代码

总结:同步代码执行区→异步代码执行区→回调函数队列
同步执行完成后,再异步代码执行区执行(完成后),再去回调函数队列,再将队列中的回调函数放入同步代码执行区执行。

你可能感兴趣的:(2019-10-30Node.js异步编程)