繁体   English   中英

异步 function - 等待不等待 promise

[英]async function - await not waiting for promise

我正在尝试学习异步等待。 在这段代码中 -

const myFun = () => {
    let state = false;

    setTimeout(() => {state = true}, 2000);

    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if(state) {
                resolve('State is true');
            } else {
                reject('State is false');
            }
        }, 3000);
    });
}

const getResult = async () => {
    return await myFun();
}

console.log(getResult());

为什么我得到 output 作为 -

Promise { <pending> }

而不是一些价值? getResult() function 不应该等待myFun() function 解析它的 promise 值吗?

如果您使用的是 async/await,则所有调用都必须使用 Promises 或 async/await。 您不能只是从同步调用中神奇地获得异步结果。

您的最终电话需要是:

getResult().then(response => console.log(response));

或类似的东西:

(async () => console.log(await getResult()))()

您需要了解的是,async/await 不会让您的代码同步运行,而是让您将其编写为:

简而言之:前面带有 async 的函数实际上是异步执行的,因此使用了关键字“async”。 并且“await”关键字将使在此异步函数中使用它的那行在其执行期间等待承诺。 因此,尽管线路等待,但整个函数仍然异步运行,除非该函数的调用者也“等待”......

更详细的解释:当你把 async 放在一个函数前面时,实际上是让它返回一个带有该函数返回的任何内容的 Promise。 该函数异步运行,当执行 return 语句时,promise 会解析返回值。

意思是,在您的代码中:

const getResult = async () => {
    return await myFun();
}

函数“getResult()”将返回一个 Promise,一旦它完成执行就会解决。 所以 getResult() 函数内的行是异步运行的,除非你告诉调用 getResult() 的函数也为它“等待”。 在 getResult() 函数中,您可能会说它必须等待结果,这使得 getResult() 的执行等待它解决 promise,但 getResult() 的调用者不会等待,除非您也告诉调用者“等待” '。

所以一个解决方案是调用:

getResult().then(result=>{console.log(result)})

或者在另一个函数中使用时,您可以简单地再次使用“等待”

async callingFunction(){
    console.log(await(getResult());
}

这是我使用带有解析拒绝机制的Promise处理等待异步的例程

    // step 1 create a promise inside a function
    function longwork()
    {
        p =  new Promise(function (resolve, reject) {
            result = 1111111111111 // long work here ; 

            if(result == "good"){
                resolve(result);
            }
            else
            {
                reject("error ...etc")
            } 
        })

        return p
    }

    // step 2 call that function inside an async function (I call it main)and use await before it
    async function main()
    {
         final_result = await longwork();
         //..

    }  

    //step 3 call the async function that calls the long work function
    main().catch((error)=>{console.log(error);})

希望可以节省一些宝贵的时间

在实际情况下,异步和等待没有意义:

Promise.resolve(3).then(console.log); console.log(4);
4
3

换句话说,由于 then() fork 和运行比后续语句慢(即使对于已解决的 Promise),那么我们需要将后续语句放在 then 中,例如:

Promise.resolve(3).then(_ => { console.log(_); console.log(4); });
3
4

既然这是真的,那为什么还要等待。 所以我还没有看到为什么 async 和 await 存在。

本次讨论中未提及的是该行为的用例含义。 在我看来,关键是要考虑您打算从顶层对 output 做什么,真正异步的 function,以及您打算在哪里做。

如果您计划立即使用 output,即在等待顶级异步 function 返回的“异步”function 中,并且您对 output 所做的操作对调用堆栈中更深层的其他函数没有任何影响,那么它更深层次的功能已经转移并不重要。 但是如果 output 需要在调用堆栈的更深处,那么您需要使用“异步”函数在堆栈中一直等待调用到该点。 一旦您到达调用堆栈中 function 不关心异步 output 的点,您就可以停止使用异步函数。

例如,在下面的代码中,function B 使用从 function A 返回的内容,因此被声明为“async”并等待 A()。 Function C() 调用 B(),返回 Promise,但可以在 promise 解析之前直接继续,因为它对 A() 的内容不感兴趣,也不关心它做了什么。 所以C不需要声明为async,也不需要await B()。

function A() {
    return new Promise((resolve, reject) => {
        //do something slow
        resolve (astuff)
    }
}
async function B() {
    var bstuff = await A();
    dosomethingwith(bstuff);
    return;
}
function C() {
    B();
    dontwaitmoveon();
    ...
    return;
}

在下一个示例中,C() 确实使用了 A() 的内容,因此需要等待它。 C() 必须声明为“异步”并等待 B()。 然而 D() 不关心 A() 的东西,也不关心它做了什么,所以一旦 C() 返回它的 promise 就继续前进。

function A() {
    return new Promise((resolve, reject) => {
        //do something slow
        resolve (astuff)
    }
}

async function B() {
    var bstuff = await A();
    dosomething();
    return bstuff;
}

async function C() {
    var cstuff = await B();
    dosomethingwith(cstuff);
    ...
    return;
}

function D() {
    C();
    dontwaitmoveon();
    ...
    return;
}

自从弄清楚这一点后,我尝试设计我的代码,以便尽可能接近源使用异步 function 返回的内容。

尽管您的“ getResult ”函数是异步的,并且您正确地对 myFun 进行了 await 调用,但请查看调用getResult函数的位置,它位于任何异步函数之外,因此它是同步运行的。

所以既然getResult是从同步的角度调用的,那么只要调用,Javascript 就会同步获取当前可用的任何结果,这是一个 Promise。

因此,异步函数的返回不能被强制等待(非常重要),因为它们与调用的来源地是同步的。

要获得您想要的,您可以运行以下命令,

async function getResult() {
  const result = await myFun();
  console.log(result);
//see no returns here
}
getResult();

暂无
暂无

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

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