异步带来的意外副作用
关键字async始终会创建一个全新的Promise,即使它附加的功能返回了自己的Promise。这会导致潜在的和意外的副作用(可能还会导致内存泄漏,但这仍有待证明,并且可以帮助验证是否值得欢迎)
介绍
Promise从用async关键字标记的函数获得的对象始终是全新的Promise(如果函数返回promise,它将被new代替Promise)。
将Promise在函数体实例不是disposed。(我们可以说这async容易导致内存泄漏吗?此声明仍然是一个悬而未决的问题,需要一些能够给出正确答案的人的帮助。)
背景
这是一个实用的技巧,而不是学术性的技巧。每个人都应该理解。
使用代码
(此处显示的代码可以直接在任何编辑器中复制和粘贴并轻松检查。不内置函数isPromise在本技巧的末尾进行了定义)
每个人都知道标有async关键字的函数始终会返回一个promise对象。因此,问题来了:
从异步标记的函数返回Promise是否正确?
我的意思是此函数定义正确吗?
async function amICorrect(){ // your implementation here return new Promise((resolve,reject) => {}); }1234复制代码类型:[html]
为了找到经验的答案,我们将使用一些小代码段。
步骤1
此功能无用,但在形式上是正确的。
var s = testS(){}; console.log("Does the function 'testS' return a 'Promise'?", isPromise(s));12复制代码类型:[html]
在这种情况下,isPromise返回false并且是正确的:testS不返回Promise。
在函数前面加上async,相同的签名现在将返回一个Promise对象。
async function testA(){} var a = testA(); console.log("Does the function 'testA' return a 'Promise'?", isPromise(a));123复制代码类型:[html]
现在,isPromise返回true。那是因为async将返回值(void在这种情况下)包装为Promise;
到现在为止还挺好。现在是时候深入探讨问题了。
第2步
此函数将动态属性添加check到新属性Promise并返回promise。
function checkS(){ var p = new Promise((resolve,reject) => {}); p.check = 'check'; return p; } var promiseS = checkS(); console.log("Is the property 'check' in the variable 'promiseS'? ", ('check' in promiseS));123456789复制代码类型:[html]
(check中promiseS)应该是true!是的!
我们在这里证明了返回值正是Promise我们在函数中实例化的对象。没有人应该感到惊讶:最后,这就是我们对函数的期望。
第三步
我们知道async将返回值包装到中Promise。如果返回值已经是一个值,会发生什么Promise?(该async函数是否足够聪明,可以理解该函数已经返回aPromise,然后返回它而不是新函数Promise?)
async function checkA(){ return await checkS(); } var promiseA = checkA(); console.log("Is the property 'check' in the variable 'promiseA'? ", ('check' in promiseA));12345复制代码类型:[html]
(check中的promiseA)应该是正确的!但事实并非如此!动态属性检查不见了!
我们还有另一项最终检查。
第四步
let globalP; async function checkLA(){ var p = checkS(); globalP = p; } var promiseLA = checkLA(); console.log(globalP);1234567复制代码类型:[html]
此代码段检查变量是否globalP仍保留对Promise在函数中创建的实例的引用checkS。是的!
在checkS其中创建的Promise仍然有效,这意味着:async不处理原始Promise对象。
因此,异步学习并不是那么聪明,开发人员必须意识到这一点。
因此,根据经验,我们可以说:
async仅在要await在函数中使用该函数时,才在该函数前添加关键字。
返回Promise从async函数将返回新品牌Promise。
'async'不是在函数主体中创建dispose的promise对象。
第3点提出了一个有关内存泄漏的新问题,如果async返回一个新Promise对象,Promise该函数返回的原始对象又如何呢?我们是否遇到内存泄漏的情况?这个问题仍然悬而未决!
用于检查变量是否为的函数Promise:
function isPromise(value){ return (!value) ? false : (Object.prototype.toString.call(value) === "[object Promise]"); }123复制代码类型:[html]
兴趣点
这段代码是以问题的形式发布在StackOverflow上的,因为当时它确实是一个问题。
人们说泄漏不是问题,并且当函数本身不返回promise时,async关键字返回aPromise。
由于我对获得的答案不满意(它们是没有任何证据的陈述),因此我决定自己找到真正的答案(第2步和第3步)。我不知道为什么,但不到一天,帖子被隐藏了。)。
因此,我认为这篇文章显示了两个兴趣点:
请注意async我们通过实际示例发现的''关键字'的实际行为。
不要相信没有给出任何证据就可以回答您问题的人。