变量不分配内部承诺 [英] variable not assigning inside promise
问题描述
也许我很困,但在什么情况下会发生以下情况?
Maybe I'm sleepy, but under what circumstances would the following occur?
let foo;
page
.evaluate(() => {
// return works... but not closure assignment
// doesn't work
foo = 'foo';
// works
return 'bar';
})
.then(bar => {
console.log('foobar', foo, bar);
// > foobar undefined bar
});
这是在使用木偶戏的摩卡测试中发生的
This is occurring in a mocha test using puppeteer
更新:完整的完整代码
节点9.11.2
/* global describe, it, before, after */
const fs = require('fs-extra');
const path = require('path');
const assert = require('assert');
const puppeteer = require('puppeteer');
const sleep = require('shleep');
const extPath = path.resolve(__dirname, '..', 'build');
const { name } = fs.readJSONSync(path.resolve(extPath, 'manifest.json'));
// Access chrome object in Extensions
// https://github.com/GoogleChrome/puppeteer/issues/2878
describe('chrome extension', () => {
let browser;
let extensionPage;
before(async function() {
this.timeout(90 * 1000);
// start puppeteer
browser = await puppeteer.launch({
headless: false,
args: [
`--disable-extensions-except=${extPath}`,
`--load-extension=${extPath}`
]
});
// poll instead of hope this is enough time?
const EXT_LOAD_DELAY = 100;
await sleep(EXT_LOAD_DELAY);
const targets = await browser.targets();
const extensionTarget = targets.find(
({ _targetInfo }) =>
_targetInfo.type === 'background_page' && _targetInfo.title === name
);
const page = await extensionTarget.page();
let foo;
page
.evaluate(() => {
// return works... but not closure assignment
// doesn't work
foo = 'foo';
// doesn't log
console.log('foo', foo);
// works
return 'bar';
})
.then(bar => {
console.log('foobar', foo, bar);
// > foobar undefined bar
});
});
it('should load', async () => {
assert(true);
});
});
测试截图
推荐答案
评估
方法在puppeteer中没有您在代码中本地或全局声明的变量概念。传递给 evaluate
方法的函数是要在页面上下文中执行的函数(即在浏览器中)。由于 foo
未在页面上下文中声明,因此无法访问它,因此无法更新其值。
The evaluate
method in puppeteer has no concept of variables that you have declared in your code either locally or globally. The function that you pass to the evaluate
method are functions that are to be executed in the page context (ie. in your browser). Since foo
is not declared in the page context, it cannot access it and therefore cannot update its value.
所以单步执行代码:
let foo;
await page.evaluate(() => {
foo = 'foo'; // Since no variable foo is known to the evaluate method in the context of your page
// this line , effectively, assigns a new variable called foo with a value 'foo' which
// is then lost once the method has completed since its value is never returned.
return 'bar'; // This value is returned from the method and is therefore retained below
})
.then(bar => {
console.log('foobar', foo, bar);
// foobar is output as expected since you've hardcoded it
// foo is now referring to the global foo you declared earlier but since you have used `let` and not
// assigned it any value, it is output as 'undefined'
// bar is the value you returned from your 'evaluate' function and is therefore output as 'bar' as
// expected in the console log.
});
如果您想使用 evaluate
来更新你的变量 foo
你必须这样做:
If you wanted to use the evaluate
to update your variable foo
you would have to do it like this:
let foo;
foo = await page.evaluate(() => {
return 'foo'
});
console.log(foo); // Now outputs 'foo' as expected
但是,您可以将变量注入评估
方法并更新它们的值(如果你愿意),例如:
You can, however, inject variables into evaluate
methods and update their values (if you wish), for example:
let foo = 'foo'
console.log(foo); // Outputs 'foo' as expected
foo = await page.evaluate((injectedFoo) => {
return `new${injectedFoo}`;
}, foo);
console.log(foo); // Outputs 'newfoo'
那么这里发生的是你注入变量 foo
进入 evaluate
方法,方法是在方法声明的末尾将其作为参数传递。 evaluate
方法现在包含一个变量(为了清楚起见,我称之为 injectFoo
),该变量带有原始值 foo
变量。
So what happens here is you've injected the variable foo
into the evaluate
method by passing it as an argument at the end of the method declaration. The evaluate
method now contains a variable (which I've called injectedFoo
for clarity) which carries the original value of the foo
variable.
然后我返回字符串 new
在 foo
变量字符串的开头附加,并在控制台中输出该值的最终值。
I'm then returning the string new
appended to the beginning to the foo
variable string and output the final value of that in the console.
我希望这有助于解释评估
方法是如何工作的!
I hope this helps to explain how the evaluate
method works!
这篇关于变量不分配内部承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!