簡體   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