变量不分配内部承诺 [英] variable not assigning inside promise

查看:65
本文介绍了变量不分配内部承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

也许我很困,但在什么情况下会发生以下情况?

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆