gpt4 book ai didi

javascript - 变量没有在 promise 中分配

转载 作者:搜寻专家 更新时间:2023-11-01 04:12:43 25 4
gpt4 key购买 nike

可能是我困了,但是在什么情况下会出现下面的情况呢?

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

这是在使用 puppeteer 的 mocha 测试中发生的

更新:完整的代码

节点 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);
});
});

测试截图

enter image description here

最佳答案

puppeteer 中的 evaluate 方法没有您在代码中本地或全局声明的变量的概念。您传递给 evaluate 方法的函数是要在页面上下文(即在您的浏览器中)中执行的函数。由于 foo 没有在页面上下文中声明,它无法访问它,因此无法更新它的值。

因此逐步执行您的代码:

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,您必须这样做:

let foo;
foo = await page.evaluate(() => {
return 'foo'
});
console.log(foo); // Now outputs 'foo' as expected

但是,您可以将变量注入(inject)evaluate 方法并更新它们的值(如果您愿意),例如:

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 作为参数传递到方法声明的末尾将其注入(inject)到 evaluate 方法中。 evaluate 方法现在包含一个变量(为清楚起见,我将其称为 injectedFoo),它带有 foo 变量的原始值。

然后我将附加到 foo 变量字符串开头的字符串 new 返回,并在控制台中输出它的最终值。

我希望这有助于解释 evaluate 方法的工作原理!

关于javascript - 变量没有在 promise 中分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51356408/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com