请教一个困扰我好久的基础问题,如何判断一个方法是不是异步的? 比如,我自己写一个自定义函数 如果是下面这样的,肯定得用await包装一下才能顺序执行:
如果是下面这样的,那方法就不用加async了,直接写就能顺序执行:
上面例子举的有点极端,但是有的方法在调用的时候真的不知道是不是异步的?如何知道我 自己写的函数 到底用不用async封装一下?或者说如何知道一个方法是不是异步的呢?
方法里面用了await的
其实最稳妥的方法就是,你要清楚这个函数的参数和返回值具体是什么,这样自然就知道它是不是异步的了。而如果确实不清楚具体的参数和返回值的含义,也可以通过一些通常都会遵循的代码风格来判断,例如:
- 如果函数的声明是
async function xxx()
或者async ()
这样的; - 如果函数返回的是一个 Promise,如
return new Promise()
; - 如果函数最后一个参数是回调函数,如
xxx(a, b, callback)
; - 如果函数体内调用了一些已知的异步函数,比如
fs.readFile()
;
当然,说一千道一万还是抵挡不住各种风骚的代码写法,所以最可靠的还是要看文档,弄清楚这个函数的参数和返回值具体是什么。
看他返回的是不是Promise?
是否可以进行默认的约定,类似Nodejs。默认都是异步的函数,如果是同步的话,函数名上加上sync。
@theanarkh 赞同,配合使用 ts 完全不会有这个疑惑
“是不是”异步函数
本质上,只要你的代码,在函数 return 之后,还会执行,都算是异步函数,比如:
function f() {
setTimeout(function() {
console.log('是的')
})
}
即使以前没有 async/await 关键字、没有 Promise,但当时,也有异步
不要去想“什么是异步函数?”,没意义
什么时候需要 async 关键字?
- 如果你的函数里出现了 await 关键字,则必须使用 async
- 否则,不需要使用 async
如何知道一个函数是不是异步的?
同第一个问题
建议
- 如果刚入门前端,可以找个完整的教程,不要抱着“写着写着就会了”的心态
对普通方法也是可以await的
function foo() {
console.log("foo()");
return "haha";
}
(async function () {
const r = await foo();
console.log(r);
})()
如果你对一个函数不确定它是不是该await,那你直接await也没问题的 异步分两种:
- 有返回值的,但是它什么时候给你返回值是不确定的,最早是通过回调函数或者EventEmitter之类的东西来实现,原理都是一样的,就是告诉它你在什么地方等他的执行结果
- 没有返回值,就是6楼写的那种,准确的说这种是启动了一个异步的任务,你当前的程序并不需要关心它的运行结果,所以没有返回值。比如在后台运行一个机器人,你需要关心的是如何让它停下来
如果想简单地通过代码判断是否是 async function 的话可以:
(async () => {}) instanceof Object.getPrototypeOf(async function(){}).constructor
@yakczh 嗯 方法里用了await的肯定是同步的,但是我要确认的他是不是异步的 function f() { setTimeout(function() { console.log(‘是的’) }) } 比如上面的函数,如果我没实验过,我就不知道他是异步的
@leizongmin 我要确认的他是不是异步的,是不是同步的好确认~~~ function f() { setTimeout(function() { console.log(‘是的’) }) } 比如上面的函数,如果我没实验过,我就不知道他是异步的
@daGaiGuanYu 本质上,只要你的代码,在函数 return 之后,还会执行,都算是异步函数,比如: function f() { setTimeout(function() { console.log(‘是的’) }) }
现在疑惑的就是这个问题,同步的函数好确认,就是异步的函数我在用代码实验以前完全不知道他是不是异步的,比如上面的代码,我知道它是异步的,可能我用的时候就给他封装成同步的,但是有的函数我不知道他的执行到底是不是异步的,如果不是异步的就没必要二次封装了,我并不想为了保险起见,把所有的函数都给封装成同步的
@iori2882 这种就是你不需要它的运行结果的,只是启动了一个异步的任务,比如每隔一段时间去获取下数据、删除下文件什么的,如果是无关紧要的任务那也不需要关心它运行是否出错什么的,就是撒手不管了 如果是重要的任务那一定会通过一些信号量来控制它的运行
.constructor.name === ‘AsyncFunction’
@iori2882 异步函数不能封装成同步函数
说一千道一万还是抵挡不住各种风骚的代码写法,所以最可靠的还是要看文档,弄清楚这个函数的参数和返回值具体是什么。
不得不说,js的代码确实比其他语言更加风骚一点.
@iori2882 通过名称一般就可以判断出来这个函数是cpu敏感
还是io敏感
。io敏感
一般都是异步函数。io敏感
的同步函数就那几个与文件操作相关的-Sync
函数,主要是方便一些工具类脚本的编写,在服务环境是不建议使用的。
看官方文档吧,里面都会标注方法的返回是一个Promise<type>还是一个type, 如果是Promise配合await就很舒服