简体   繁体   English

.then() 不会等到异步 function 解析 promise?

[英].then() doesn't wait till async function resolves promise?

I have two functions.我有两个功能。 First contains jQuery.get().done() and it's return value is inside done() callback function, as showed below.首先包含 jQuery.get().done() ,它的返回值在 done() 回调 function 内部,如下所示。 (I have no idea if using jQuery matters here) (我不知道在这里使用 jQuery 是否重要)

I may not be understanding something, but my functions looks similar to those in first w3 example: https://www.w3schools.com/js/js_async.asp我可能不明白,但我的功能与第一个 w3 示例中的功能相似: https://www.w3schools.com/js/js_async.asp

async function A(){     
  jQuery.get("example.com").done(function(result){
    if (result.indexOf("Example")){
      console.log("sucess");
      return 1;
    } else {
      console.log("Fail");
      return -1;
    }
  })
}

function B(){
  A().then(function(result){
    console.log("Res:" + result);
  })
}

B();

But the output is:但是 output 是:

 Res:undefined // here some time passes for A() to complete. succes

So I can't understand why.then() doesn't wait for function A() to complete and resolve promise, but instead it acts immediately while result is not defined yet?所以我不明白为什么。then() 不等待 function A() 完成并解决 promise,而是在尚未定义结果时立即起作用?

This is much better written using actual promises (which jQuery supports) and await as follows:使用实际的 Promise(jQuery 支持)写得更好, await如下:

async function A() {
    const result = await jQuery.get("example.com");
    if (result.indexOf("Example") !== -1) {
        console.log("sucess");
        return 1;
    } else {
        console.log("Fail");
        return -1;
    }
}

Notes:笔记:

  1. Stop using jQuery's .done() .停止使用 jQuery 的.done() It's non-standard.这是非标准的。 Use .then() or await .使用.then()await
  2. Don't mix await with .done() or with .then() .不要将await.done().then() () 混合使用。 Use one model or the other.使用一个 model 或另一个。
  3. There's no need for the res intermediate variable.不需要res中间变量。 When you get rid of the .done() , you can just return the value directly.当您摆脱.done()时,您可以直接返回该值。
  4. Note, .indexOf() does not return a boolean.注意, .indexOf()不返回 boolean。 It returns -1 if not found and an index of the position if found.如果未找到,则返回 -1,如果找到,则返回 position 的索引。 Best not to treat its return value as a boolean.最好不要将其返回值视为 boolean。

This isn't really a jQuery thing in particular.这并不是真正的 jQuery 事情。 It's just async JS in general.一般来说,它只是异步 JS。 I'm not sure you really need the.done() part at all since you're using promises.不确定您是否真的需要 the.done() 部分,因为您使用的是 Promise。

But anyway, you have two basic problems.但无论如何,你有两个基本问题。

  1. You need to return something inside of function A, not inside .done() .您需要返回 function A 内部的东西,而不是.done()内部。 So you can return jQuery.get() .所以你可以返回jQuery.get()

  2. In function B, you want to wait for function A to complete before hitting the .then() block.在 function B 中,您要等待 function A 完成,然后再点击 .then .then()块。 That means function B is also async.这意味着 function B 也是异步的。 (In the simple example below you can omit the async keyword on function A.) You need to declare function B as async and then await the completion of function A. (在下面的简单示例中,您可以省略 function A 上的async关键字。)您需要将 function B 声明为async ,然后await ZC1C425268E68385D14AB5074C17A9A9 完成。

function A() {
  return jQuery.get("example.com").done(function(result) {
    if (result.indexOf("Example")) {
      console.log("sucess", result);
    } else {
      console.log("Fail", result);
    }
  });
}

async function B() {
  await A().then(function(result) {
    console.log("Res:");
    // moved to a separate console log, otherwise dev tools might print
    // a lot of [objectObject] instead of the actual result
    console.log(result);
  })
}

B();

If you want to do other stuff inside of function A and then eventually return the result, you can play around with something more like如果你想在 function A 内部做其他事情,然后最终返回结果,你可以玩一些更像

async function A() {
  const response = await jQuery.get('example.com');
  // more stuff…
  return response;
}

I fixed it by moving return statement outside from the.done(function(){}) and by adding await before jQuery chain.我通过将 return 语句从 the.done(function(){}) 移到外部并在 jQuery 链之前添加 await 来修复它。 And instead of returning value inside that callback function, now I only pass there value to variable, which is later returned outside of that callback function.而不是在该回调 function 中返回值,现在我只将值传递给变量,该变量稍后在该回调 function 之外返回。

async function A(){     
 let res = 0; 
  await jQuery.get("example.com").done(function(result){ //await was added
    if (result.indexOf("Example")){
      console.log("sucess");
      res = 1; // value is passed to variable, which is returned as result outside this callback function
    } else {
      console.log("Fail");
      res = -1;
    }
  })
  return res; // return statement is outside the callback function
}

function B(){
  A().then(function(result){
    console.log("Res:" + result);
  })
}

B();

I guess the problem was, as @cjl750's answer says, that return statement inside the callback function isn't "seen" as a "true return statement" of that function.我想问题是,正如@cjl750 的回答所说,回调 function 中的 return 语句没有被“视为”为 function 的“真正的返回语句”。 So function B() probably saw function A() as a function, which doesn't return anything.所以 function B() 可能将 function A() 视为 function,它不会返回任何内容。


EDIT编辑

I've rewritten the code using $.Deferred() object.我已经使用 $.Deferred() object 重写了代码。 It's probably better now.现在应该好多了。 Await is now moved to function B(), it doesn't wait for jQuery chain anymore. Await 现在移至 function B(),它不再等待 jQuery 链。

function A(){     
 var dfd = $.Deferred();
 jQuery.get("google.com").then(function(result){ 
    if (result.indexOf("Example")){
      console.log("sucess");
      dfd.resolve(1); 
    } else {
      console.log("Fail");
      dfd.resolve(-1); 
    }
  })
  return dfd.promise();
}

async function B(){
  await A().then(function(result){
    console.log("Res:" + result);
  })
}

B();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM