Javascript 值未定义:异步中的循环使用Promise.race等待?

Javascript 值未定义:异步中的循环使用Promise.race等待?,javascript,node.js,promise,async-await,Javascript,Node.js,Promise,Async Await,我正在从事一个项目,在这个项目中,我需要暴力破解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 fin

我正在从事一个项目,在这个项目中,我需要暴力破解
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)); 

通过调用
返回新的Promise.resolve(currentPass)
将结果返回到
然后
,而不是从
ATryCase
返回。将
wait 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;
如果
currentPass
正确,我需要中断循环并返回值

到目前为止,您的代码片段都没有这样做。您将需要使用类似于

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

您的原始代码(只有一个循环)不使用
await
,将同时触发所有
myFunc.getDocument(…)
调用。您的
ATryCase
函数按顺序执行调用(
一个接一个地等待它们),因此如果有什么问题,它应该会慢一些。如果这两个函数占用相同的时间,则表明您的
getDocument
函数仍然执行内部排队,几乎没有改进的余地。如果您的
ATryCase
函数访问多个文档(而不仅仅是一个文档),您希望它返回什么值?1。我从来没有说过我的单循环使用wait。我说了为什么普通循环和基于承诺的循环需要相同的时间,而基于承诺的循环被划分为多个作业。2.
myFunc.getDocument
是一个基于承诺的函数,如果我不在上面使用wait,那么函数就乱七八糟了。getDocument做的不多。它只是验证
currentPos
是否是要处理的正确值。把它看作是一个密码检查程序。每次验证
currentPos
是否为真时,中断循环并返回currentPos。您所说的“划分为多个作业”是什么意思?每个
myFunc.getDocument(…)
都已经是它自己的作业了。唯一的区别是一次叫他们所有人还是一个接一个地叫他们。不善于使用准确的词语。我的意思是
使用Promise.race
。4
ATryCase
每次调用30次迭代,首先找到它的人返回它。我没有得到它。重点是什么?在循环中使用它将使它在第一次迭代中退出。仅当myFunc为true或已解析时,我才需要返回当前过程。在原始代码中没有关于检查
true
的代码。如果
myFunc.getDocument
成功解析,则执行
return res
。如果
myFunc.getDocument
被拒绝,那么您将被抛出
ATryCase
,您可以在
catch
块外部捕获此案例。是否要返回第一次成功执行的
myFunc.getDocument
,而不考虑以前被拒绝的尝试?当
myFunc
解决问题时,我需要停止并返回
currentPass
的值。我在函数中尝试过,但没有成功。我从不拒绝myFunc,为什么?因为我使用的是
race
,其中返回了第一个解析的承诺,我只想解析一个发现值正确的承诺。我希望我解释得很好。
到目前为止,您的代码片段都没有这样做
我使用基于promise的函数来做,只是想知道异步函数有什么问题。然而,这是第二个问题,主要是为什么在使用
promise.race
时没有性能提升?单循环迭代89次,在450ms内完成,而多次调用函数的race也在450ms内完成。这是为什么。@ChandraShekharAazad如果“基于承诺的函数”指的是第一个片段,不,当发现某个东西时,它没有停止迭代,而且它根本没有从函数返回任何内容。它只记录它发现的结果。@ChandraShekharAazad以及为什么使用
Promise.race没有任何改进,我已经在关于这个问题的评论中解释过了。原始代码没有按顺序执行任何操作,而是并行执行(同时启动所有调用)。使用
wait
充其量只能意味着减速。嘿@Bergi你能看一下吗?在更新的问题上
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");
}
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);
}