Why does assignment using await within while expression not retain assigned value?

二次信任 提交于 2019-11-28 14:15:40

问题


Given the JavaScript code

function* gen(start = 0, stop = 5) {
   while (start < stop) yield ++start;
}

async function fn(g = gen()) {
  while (done = !await new Promise(resolve => 
                   setTimeout(resolve, 1000, g.next()))
                   .then(({value, done}) => {
                     // `value:undefined, done:true` following
                     // `value:5, done:false`
                     console.log(`value:${value}, done:${done}`); 
                     return done 
                   }
                   , err => Promise.reject(err)));
  return done; // what happened to the `true` value assigned?
}
// why is `res` `false`?
fn().then(res => console.log(`res:${res}`), err => console.error(err));

the expected result of done returned from fn() is true when done is assigned the value true that is returned from .then() within while expression.

Why is the assignment using await at while statement expression not retained?


回答1:


JavaScript has "three" different types of scope: local, global, and block.

Global

This type of variable can be reach in all places of the code:

var b = "bar";
   (function test1(a) {
         if (a == true) {
              var b = "bar";
         } else {
              var b = "foo";
         }
         return b;
    })(true);
    alert(b);

Local

These variables can only be reached if the variable in the general scope of the code:

(function test2(a) {
     if (a == true) {
          var b = "bar";
     } else {
          var b = "foo";
     }
     return b;
})(true)

In this case, the general scope is the function. Even though the variable b is block scoped by the if statement, the function can still reach it.

Block

Self defined block scoped variables are pretty new to JavaScript and can be introduced using the let keyword:

(function test2(a) {
     if (a == true) {
          let b = "bar";
     } else {
          let b = "foo";
     }
     return b;
})(true)

This will result in an error because the variable b is now block scoped to the if state. Thus in your code, we can change your scoping to allow you to change done which in a while loop is block scoped in the case of asynchronous loops.

function* gen(start = 0, stop = 5) {
   while (start < stop) yield ++start;
}

async function fn(g = gen()) {
  let doneVal;
  while (done = !await new Promise(resolve => 
                   setTimeout(resolve, 1000, g.next()))
                   .then(({value, done}) => {
                     // `value:undefined, done:true` following
                     // `value:5, done:false`
                     console.log(`value:${value}, done:${done}`); 
                     return done 
                   }
                   , err => Promise.reject(err))) {
       doneVal = done;
  }

  return doneVal; // what happened to the `true` value assigned?
}
// why is `res` `false`?
fn().then(res => console.log(`res:${res}`), err => console.error(err));

Now you will get res:true. In your specific example, there is an issue with code like this:

var i;
var c = 0;
while (i = 90 && c < 10) {
    c++;
}
console.log(i, c);

i is false while c is equal to 10




回答2:


The comments by @JaromandaX helped recognize that the ! was not in correct place within code to return expected result. The Answer by @Shawn31313 reminded to define variable using parameter or let within function call, as done being defined as a global variable was not intended

function* gen(start = 0, stop = 5) {
   while (start < stop) {
     yield ++start;
   }
}
async function fn(g = gen()) {
  let done;
  while ((done = await new Promise(resolve => 
                   setTimeout(resolve, 1000, g.next()))
                   .then(({value, done}) => {
                     console.log(value, done); 
                     return !done
                   }
                   , err => Promise.reject(err))));
  return !done;
}

fn().then(res => console.log(res), err => console.error(err));


来源:https://stackoverflow.com/questions/47171474/why-does-assignment-using-await-within-while-expression-not-retain-assigned-valu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!