异步带来的意外副作用

关键字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我们通过实际示例发现的''关键字'的实际行为。

不要相信没有给出任何证据就可以回答您问题的人。

(0)

相关推荐