JS中的Async/Await与Promise和Callbacks的区别

4

我正在尝试理解这三者之间的区别。回调函数和 Promise 很清楚,但我不明白 async/await 的用法。我知道它是 Promise 的语法糖,但我所尝试的并没有起作用。我分享了一段我尝试理解所有这些的代码...

我已经尝试使用一个数组

var array = [1,2,3];

还有两个函数

  • get() 在1秒内执行并在控制台打印array
  • post(item) 在2秒内执行并将一个新项推入array

现在,我想要的是post方法应该先执行,然后才是get,以便在控制台上的结果应该是[1,2,3,4]而不是[1,2,3]

回调函数

function get() {
    setTimeout(() => console.log(array), 1000);
}

function post(item, callback) {
    setTimeout(() => {
        array.push(item);
        callback();
    }, 2000);
}

function init() {
    post(4, get);
    // returns [1,2,3,4] ✅
}

虽然运行良好,但如果回调函数过多,则代码将变得混乱...

承诺(Promise)

function get() {
    setTimeout(() => console.log(array), 1000);
}

function post(item) {
    return new Promise((resolve, reject) => setTimeout(() => {
        array.push(item)
        resolve();
    }, 2000));
}

function init() {
    post(4).then(get);
    // returns [1,2,3,4] ✅
}

代码变得更加简洁了。但是仍然有多个then调用... 现在,

Async/Await

function get() {
    setTimeout(() => console.log(array), 1000);
}

function post(item) {
    setTimeout(() => {
        array.push(item)
    }, 2000);
}

async function init() {
    await post(4);
    get();
    // returns [1,2,3] ❌

    await post(4);
    await get();
    // returns [1,2,3] ❌

    post(4);
    await get();
    // returns [1,2,3] ❌
}

更干净的版本,但无论哪种方式,都不起作用...我也尝试过这个方法(将postget两个函数都转换为异步函数,并使用then调用)

async function get() {
    setTimeout(() => console.log(array), 1000);
}

async function post(item) {
    setTimeout(() => {
        array.push(item)
    }, 2000);
}

async function init() {
    post(4).then(get);
    // returns [1,2,3] ❌
}

但仍然没有用。所以我对这个特性(即async/await)完全感到困惑。请详细解释这个例子。同时,请在同一上下文中告诉我关于Promise.resolvePromise.all的内容!谢谢


1
当您将init.then()语法更改为await语法时,仍需要使用返回Promise的post函数。 - Bergi
3个回答

5

asyncawait 是用来管理 Promise 的工具。

await post(4);
你在这里等待由post返回的Promise被解决。
function post(item) {
    setTimeout(() => {
        array.push(item)
    }, 2000);
}

然而,post 并不返回一个promise,所以它没有任何用处。

你以前使用过带有promise的post的有效实现。因此请使用它:

function post(item) {
    return new Promise((resolve, reject) => setTimeout(() => {
        array.push(item)
        resolve();
    }, 2000));
}

1
这是否意味着 async/await 只是 .then() 的替代品? - TalESid
如果我使用 Promise.resolve(...) 而不是 return new Promise((resolve, reject) => ...),它会起作用吗? - TalESid
2
大致上不会,因为Promise.resolve返回一个已解决的Promise,所以它会在超时结束之前就被解决。 - Quentin

4

您使用asyncawait的尝试并未使用任何在延迟后解决承诺的内容。目前为止,您定义的所有async函数都会立即解决一个Promise。

您需要使用一个实用程序函数,通常使用它。该函数将在指定的毫秒数之后使用setTimeout返回一个解析的Promise:

// utility function
let delay = ms => new Promise(resolve => setTimeout(resolve, ms));

let array = [1, 2, 3];

async function get() {
    await delay(1000);
    console.log(array);
}

async function post(item) {
    await delay(1000);
    array.push(item)
}

async function init() {
    await post(4);
    await get();
}

init();
console.log("wait for it...");


非常感谢您提供的实用函数 :) - TalESid

1

类似于您在 PROMISE 中所做的。

将 post setTimeout 包装在一个 Promise 中并返回。
在 settimeout 的主体内调用 resolve。

function post(item) {
 return new Promise((resolve)=>{
   setTimeout(() => {
     array.push(item)
     resolve()
   }, 2000);
 })
}

然后你可以像这样使用它:
async function init() {
    await post(4);
    get();
    }


太好了,我的长期困惑现在解决了 :) - TalESid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接