【问题标题】:Javascript - PromisesJavascript - 承诺
【发布时间】:2021-05-18 02:30:22
【问题描述】:

您好,我的代码需要帮助。我对 Promises 不是很熟悉。我创建了一个名为 EmitRandomNumber() 的函数。在这个函数中,经过整整 2 秒(2000 毫秒),它会生成一个介于 0 到 100 之间的随机数。如果生成的随机数低于 80,我需要再次调用该函数,最多 10 次,直到生成随机数大于 80。

let attempt = 1;
let rN; 
function EmitRandomNumber() {
    return new Promise((resolve, reject)=> {
        console.log(`Attempt #${attempt}. EmitRandomNumber is called.`);
        setTimeout(()=>{
            let randomNumber = Math.floor(Math.random() * 100) + 1;
            rN = randomNumber;
            console.log("2 seconds have passed.");
            
            if(randomNumber>=80&&attempt<=10){
                console.log(randomNumber,attempt);

                resolve();
            }else if(randomNumber<80&&attempt<=10){
                attempt++;
                console.log(`Random number generated is ${randomNumber}.`);
                console.log("===============================");
                EmitRandomNumber();
            }
        },2000);
    });
  }

let promise = EmitRandomNumber();

promise.then(()=>{
    console.log(`Random number generated is ${rN}!!!!`);
    console.log("===============================");
}).catch(()=>{
    console.log("End");
});

我不知道我是否正确使用了 Promise,有时当它高于 80 时,它不会执行解析中的任何代码。你能帮我解决我的代码吗?谢谢!

【问题讨论】:

  • 所以如果数字不好,您是否希望它再等 2 秒再重试?还是应该立即进行新尝试(在 2 秒标记处)?
  • 如果生成的数字低于 80,则 2 秒后我生成另一个数字,直到它达到尝试 #10 或高于 80 的数字
  • 你永远不会在 else 分支中调用 resolve()stackoverflow.com/questions/49014833/…stackoverflow.com/a/53032742/1048572

标签: javascript asynchronous


【解决方案1】:

所以代码大部分都很好,只是您没有指定何时“拒绝”承诺。根据您的描述,如果承诺在 10 次尝试后未找到数字,则您希望它“拒绝”(或显示 console.log('End'))。所以你只需要添加一个条件(如果尝试===10)等。

编辑:需要返回解决和拒绝。

let attempt = 1;
let rN; 
function EmitRandomNumber() {
    return new Promise((resolve, reject)=> {
        console.log(`Attempt #${attempt}. EmitRandomNumber is called.`);
        setTimeout(()=>{
            let randomNumber = Math.floor(Math.random() * 100) + 1;
            rN = randomNumber;
            console.log("2 seconds have passed.");
            if(randomNumber>=80&&attempt<=10){
                console.log(randomNumber,attempt);
                return resolve();
            }else if(randomNumber<80&&attempt<=10){
                attempt++;
                console.log(`Random number generated is ${randomNumber}.`);
                console.log("===============================");
                EmitRandomNumber();
//CHECK FOR CONDITION NUMBER OF ATTEMPTS
            } else if(attempt>10){
                 return reject();
            }
        },2000);
    });
  }


let promise = EmitRandomNumber();

promise.then(()=>{
    console.log(`Random number generated is ${rN}!!!!`);
    console.log("===============================");
}).catch(()=>{
    console.log("End");
});

【讨论】:

  • 感谢您的帮助!但是我运行了代码,在第三次尝试后它生成了 97,但它没有在解析中执行代码。
  • 如果在第一次尝试中生成的数字大于 80,它会执行 resolve(),但在随后的尝试中,当它生成大于 80 的数字时,它不会记录 resolve() 中的任何内容,而是终止程序
  • 需要返回解析。进行编辑以便您查看。我的错。
【解决方案2】:

使用异步函数和等待可能更容易阅读和推理。例如:

const MAX_TRIES = 10;

const sleep = (ms) => {
    return new Promise(resolve => setTimeout(resolve, ms));
}

const getRandomNumber = () => {
    return Math.floor(Math.random() * 100) + 1;
}

const getNumberWaitAndReturn = async () => {
    let rN = getRandomNumber();
    let attempt = 1;

    while (rN < 80 && attempt <= MAX_TRIES) {
        await sleep(2000);
        rN = getRandomNumber();
        attempt += 1;
    }

    if (attempt > MAX_TRIES) {
        console.log(attempt)
        throw new Error("No luck! It took more than 10 tries!")
    }

    return {
        rN,
        attempt
    }
}

const result = getNumberWaitAndReturn().then(v => {
    console.log(v)
});

【讨论】:

    【解决方案3】:

    你做得很好,你只需要多练习一下就可以做得更好,我强烈建议你开始使用闭包,而不是像在代码中那样声明全局变量。

    在告诉你如何解决这个问题之前,我会告诉你这是错误,你的函数只有在它第一次执行时会产生一个大于 80 的随机数,你的函数才会按预期工作,否则函数将永远不会解决了,为什么?那是因为每次您将 EmitRandomNumber() 调用到函数本身时,您都会创建一个 new Promise 引用,因此您创建的第一个引用永远不会被处理,因为您创建了一个新的引用承诺,所以新的引用,它没有句柄,因为您的在函数内部调用,没有人在做.then(...)

    那么如何解决呢?首先,您需要创建一个closure 来创建它。

    const emitRandomNumber = () => {
      const MAX_ATTEMPTS = 10;
      const MS_START_TIME = 2000;
      const MINIMUM_NUMBER = 80;
      const MAXIMUM_NUMBER = 100;
      let attempts = 0;
      const randomNumber = (max) => Math.floor(Math.random() * max);
      return new Promise((resolve, reject) => {
        const startRandomNumber = () => {
          attempts++;
          const number = randomNumber(MAXIMUM_NUMBER);
          if (number < MINIMUM_NUMBER && attempts <= MAX_ATTEMPTS) {
            return setTimeout(startRandomNumber, MS_START_TIME);
          }
          if (number < MINIMUM_NUMBER && attempts > MAX_ATTEMPTS) {
            return reject();
          }
          resolve(number);
        };
        setTimeout(startRandomNumber, MS_START_TIME);
      });
    }
    

    如你所见,我们使用闭包在函数体内创建函数,所以我们再次调用的唯一函数是 startRandomNumber 函数,所以这不会生成新的 Promise 实例,而是保持相同的 Promise参考,我们只是执行随机数函数,直到达到尝试为止。

    【讨论】:

      猜你喜欢
      • 2020-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-27
      相关资源
      最近更新 更多