【问题标题】:Value Undefined: Loops in async await with Promise.race?值未定义:与 Promise.race 异步等待的循环?
【发布时间】:2020-09-28 02:35:00
【问题描述】:

我正在做一个需要暴力破解PDF密码的项目。

因为PDF.js 用于验证密码,promise.race 用于运行并行函数以使整体工作快速。

这就是我实现它的方式:

var sfile = "KRIS.pdf"
var dBuf = fs.readFileSync(sfile);
const tryCases = getCombos(alphaArray, 4); // permutation having total length 456976
var finishFunction = false;
async function getPass(startAt = Number(), endAt = Number()) {
  var isDone = false;
  var currentPass = ''
  for (let index = startAt; index < endAt; index++) {
    if (finishFunctions) { return; }
    currentPass = tryCases[index].join("");

    await pdfjsLib.getDocument({ data: dBuf, password: currentPass }).promise
      .then((r) => {
        console.log('Worked: ' + currentPass);
        isDone = true;
        pdfjsLib.distroy();
        return new Promise.resolve();
      })
      .catch((e) => {  })

    if (isDone) {
      finishFunctions = true;
      return currentPass;
    }
  }
console.log(`Hey Nothing From ${startAt} - ${endAt}`);
}

console.time('Found ');
Promise.race([
  getPass(0, 100000),
  getPass(100000, 200000),
  getPass(200000, 300000),
  getPass(300000, 400000),
  getPass(400000, 456976)
])
  .then((s) => { console.timeEnd('Found '); console.log('HeyThen ' + s) })
  .catch((e) => console.log('Hey Error ' + e)); 

现在可以获取 4 个字母的密码,但是有问题阻止它完成。

第一个当前函数非常慢,即使在运行并行函数之后也需要很长时间。

第二次我添加了一个标志来停止其他并行功能,但它无法按预期使用 4 个字母强制。

第三资源使用率真的很高。我的 Linux 系统停止响应。

为了可视化时间和标志问题,我使用了 3 个字母强制,这里是它的日志:

Worked: KRIS
Found: 13950.743ms
HeyThen KRIS
Hey Nothing From 4934 - 8788
Hey Nothing From 0 - 4394
Hey Nothing From 13182 - 17576
(node:3068) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead. 

【问题讨论】:

  • 您的原始代码(只有一个循环)不使用await,并且会同时触发所有myFunc.getDocument(…) 调用。您的 ATryCase 函数按顺序执行调用(await 一个接一个地调用它们),所以如果有的话,它应该会更慢。如果它们都花费相同的时间,则表明您的 getDocument 函数无论如何都会进行内部排队,并且几乎没有改进的余地。
  • 鉴于您的 ATryCase 函数访问多个文档(不仅仅是一个文档),您希望它返回什么值?
  • 1.我从来没有说过我的单循环使用等待。我说过为什么正常循环需要与基于承诺的循环相同的时间,后者分为多个工作。 2. myFunc.getDocument 是基于 promise 的函数,如果我不使用 await ,那么函数就会混乱。 getDocument 没有做太多。它只是验证currentPos 是否是要处理的正确值。将其视为密码检查程序。每次验证 currentPos 是否为真时,都会中断循环并返回 currentPos。
  • 你说的“分成多个工作”是什么意思?每个myFunc.getDocument(…) 已经是它自己的工作。唯一的区别是一次调用它们还是一个接一个地调用它们。
  • 不擅长使用精确的词。我的意思是using of Promise.race。 4 ATryCase 被调用,每次迭代 30 次,第一个找到它的人会返回它。

标签: javascript node.js promise async-await


【解决方案1】:

通过调用return new Promise.resolve(currentPass);,您将结果返回给then,而不是来自ATryCase。将await myFunc.getDocument的结果写入某个变量并返回

const res = await myFunc.getDocument({ data: dBuf, pos: currentPass })
      .promise
      .then(() => {
        console.log('Data is: ' + currentPass);
        console.timeEnd('GotData ');
        return new Promise.resolve(currentPass);
      }).catch(e => { });
return res;

【讨论】:

  • 我没明白。重点是什么 ?在循环内使用它会使其在第一次迭代中退出。仅当 myFunc 为真或已解决时,我才需要返回当前通行证。
  • 原始代码中没有关于检查true 的代码。如果myFunc.getDocument成功解析,则执行return res。如果myFunc.getDocument 被拒绝,那么您将被排除在ATryCase 之外,您可以在catch 块中捕获此案例。是否要返回第一次成功执行 myFunc.getDocument 而不管之前的尝试被拒绝吗?
  • myFunc 解析时,我需要停在那里并返回 currentPass 的值。我在函数中尝试过,但没有奏效。我从不拒绝 myFunc,为什么?因为我使用的是race,其中返回了第一个已解决的承诺,我只想解决一个发现值正确的承诺。我希望我解释得很好。
【解决方案2】:

如果currentPass 正确,我需要打破循环并返回值

到目前为止,您的任何代码 sn-ps 都没有这样做。你会想要使用类似的东西

async function ATryCase(indexStart, indexEnd) {
  for (let index = indexStart; index < indexEnd; index++) {
    var currentPass = startLetters + index;
    try {
      await myFunc.getDocument({ data: dBuf, pos: currentPass }).promise;
      console.log('Data is: ' + currentPass);
      return currentPass; // this breaks the loop and `return`s from ATryCase
    } catch {
      continue;
    }
  }
  throw new Error("No pass did find a result");
}

为此。

或者,看看建议的Promise.any,它可以完全满足您的需求,但同时进行。 (如果您进行 4 个并发顺序搜索,您还需要使用它来代替 Promise.race)。你可以像这样使用它

function ATryCase(indexStart, indexEnd) {
  const promises = [];
  for (let index = indexStart; index < indexEnd; index++) {
    var currentPass = startLetters + index;
    promises.push(myFunc.getDocument({ data: dBuf, pos: currentPass }).promise.then(() => {
      console.log('Data is: ' + currentPass);
      return currentPass;
    }));
  }
  return Promise.any(promises);
}

【讨论】:

  • None of your code snippets did that so far 我使用基于 promise 的函数来做这件事,只是想知道异步函数有什么问题。然而这是次要问题,主要是为什么使用 promise.race 时没有性能提升?单个循环迭代 89 次并在 450 毫秒内完成,而多次调用该函数的 promise.race 在 450 毫秒内完成它太慢了,为什么会这样。
  • @ChandraShekharAazad 如果“基于承诺的函数”是指第一个 sn-p,不,它在发现某些东西时没有停止迭代,并且它没有 return 函数中的任何内容一点也不。它只记录它找到的结果。
  • @ChandraShekharAazad 为什么使用Promise.race 没有改善我已经在 cmets 中解释了这个问题。原始代码没有按顺序执行任何操作,而是并行执行(同时启动所有调用)。使用await 充其量意味着减速。
  • 嘿@Bergi 你能看看吗?在更新的问题
猜你喜欢
  • 2020-04-12
  • 2020-05-30
  • 1970-01-01
  • 2021-04-15
  • 2019-07-02
  • 1970-01-01
  • 2019-08-07
  • 1970-01-01
  • 2017-12-12
相关资源
最近更新 更多