函数返回后,JavaScript中调用堆栈中的变量如何仍然可以访问
有两点混淆:函数返回后,JavaScript中调用堆栈中的变量如何仍然可以访问,javascript,promise,callstack,asynchronous-javascript,Javascript,Promise,Callstack,Asynchronous Javascript,有两点混淆: 如何保存和处置功能框架 例如: function foo() { var a = ...; setTimeout(function() { console.log(a); },50); return a; } async function foo2() { var p = new Promise() { setTimeout(function() { p.reject(null); },60000); p.resol
function foo() {
var a = ...;
setTimeout(function() {
console.log(a);
},50);
return a;
}
async function foo2() {
var p = new Promise() {
setTimeout(function() {
p.reject(null);
},60000);
p.resolve(await dbcall.execute());
}
return p;
}
在本例中,setTimeout中的内部函数引用外部变量a,即使在foo返回之后也是如此。来自Java世界,我很困惑这是如何发生的?如何存储foo堆栈帧以供内部函数使用,以及何时从堆栈中弹出
function foo() {
var a = ...;
setTimeout(function() {
console.log(a);
},50);
return a;
}
async function foo2() {
var p = new Promise() {
setTimeout(function() {
p.reject(null);
},60000);
p.resolve(await dbcall.execute());
}
return p;
}
在其他地方:
foo2.then(resolve, reject) {
...
}
假设首先发生超时调用,然后dbcall返回。这一承诺可能会得到两次解决
问题:在超时调用被拒绝后,函数是否仍然保持(a)等待db调用返回,然后执行wait之后出现的任何代码?第二次履行承诺(即等待完成时的解析调用)会发生什么情况?只有第一次解析/拒绝得到处理吗
来自Java世界,我很困惑这是如何发生的
这叫做结束
函数引用的所有变量都保留在该函数的作用域中,无论它位于何处或何时执行。这是JavaScript的基本原则之一
你的第二个例子没有意义
- 将函数声明为
的唯一原因是希望在内部使用async
wait
- 如果内部函数返回承诺,则返回该承诺。不要创建新的(请参见)
function foo2() {
return dbcall.execute();
}
或者,用粗箭头语法
const foo2 = () => dbcall.execute();
为了生成超时,可以使用Promise.race()
但是如果你想用一个新的承诺来包装它,你可以——以牺牲可组合性为代价:
const foo2 = () => new Promise((resolve, reject) => {
dbcall.execute().then(resolve).catch(reject);
setTimeout(() => reject('timeout'), 60000);
});
在超时调用被拒绝后,函数是否仍保持(a)等待db调用返回
是的,这两件事都是独立执行的。除非构建相互取消机制,否则setTimeout()
和dbcall.execute()
都将运行到完成
第二次履行承诺(即等待完成时的解析调用)会发生什么情况?是否只处理第一次解析/拒绝
无论事实发生后有多少内部函数调用
reject
或resolve
。“是否只处理了第一个解决/拒绝?”似乎很容易测试出……1。二,。这是一个承诺,这意味着它检查它是否得到解决,承诺本身就是一个目标;第二个知道它已经完成,并且马上决定(或拒绝)。这就像一个任务,如果Java有类似的东西(这里是C#person)假设超时调用首先发生,然后dbcall返回。承诺可能会被解决两次
不真实。。第一次解决/拒绝将履行“功能框架如何保存和处置?”的承诺。问题:每个功能都创建了一个新的范围。正如您所期望的那样,作用域是嵌套的,并从内部向外引用。函数是对象——只要它们是活动的,它们的引用就不会被垃圾收集。这适用于执行延迟的函数。警告:外部作用域值可能在引用它的函数运行之前更改。作用域仅捕获变量引用,您将始终获得当前值。@Tomalak谢谢!