异步带来的意外副作用

开课吧开课吧锤锤2021-05-08 16:22

点赞
有用
分享分享

    关键字async始终会创建一个全新的Promise,即使它附加的功能返回了自己的Promise。这会导致潜在的和意外的副作用(可能还会导致内存泄漏,但这仍有待证明,并且可以帮助验证是否值得欢迎)

web

    介绍

    Promise从用async关键字标记的函数获得的对象始终是全新的Promise(如果函数返回promise,它将被new代替Promise)。

    将Promise在函数体实例不是disposed。(我们可以说这async容易导致内存泄漏吗?此声明仍然是一个悬而未决的问题,需要一些能够给出正确答案的人的帮助。)

    背景

    这是一个实用的技巧,而不是学术性的技巧。每个人都应该理解。

    使用代码

    (此处显示的代码可以直接在任何编辑器中复制和粘贴并轻松检查。不内置函数isPromise在本技巧的末尾进行了定义)

    每个人都知道标有async关键字的函数始终会返回一个promise对象。因此,问题来了:

    从异步标记的函数返回Promise是否正确?

    我的意思是此函数定义正确吗?

async function amICorrect(){
    // your implementation here
    return new Promise((resolve,reject) => {});
}

    为了找到经验的答案,我们将使用一些小代码段。

    步骤1

    此功能无用,但在形式上是正确的。

var s = testS(){};
console.log("Does the function 'testS' return a 'Promise'?", isPromise(s));

    在这种情况下,isPromise返回false并且是正确的:testS不返回Promise。

    在函数前面加上async,相同的签名现在将返回一个Promise对象。

async function testA(){}
var a = testA();
console.log("Does the function 'testA' return a 'Promise'?", isPromise(a));

    现在,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));

    (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));

    (check中的promiseA)应该是正确的!但事实并非如此!动态属性检查不见了!

    我们还有另一项最终检查。

    第四步

let globalP;
async function checkLA(){
    var p = checkS();
    globalP = p;
}
var promiseLA = checkLA();
console.log(globalP);

    此代码段检查变量是否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]");
}

    兴趣点

    这段代码是以问题的形式发布在StackOverflow上的,因为当时它确实是一个问题。

    人们说泄漏不是问题,并且当函数本身不返回promise时,async关键字返回aPromise。

    由于我对获得的答案不满意(它们是没有任何证据的陈述),因此我决定自己找到真正的答案(第2步和第3步)。我不知道为什么,但不到一天,帖子被隐藏了。)。

    因此,我认为这篇文章显示了两个兴趣点:

    请注意async我们通过实际示例发现的''关键字'的实际行为。

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

    以上就是开课吧广场小编为大家整理发布的“异步带来的意外副作用”一文,更多Web教程相关内容尽在开课吧广场Web教程频道!

有用
分享