【问题标题】:Async function return before object with data built [duplicate]异步函数在构建数据的对象之前返回[重复]
【发布时间】:2019-05-02 06:59:17
【问题描述】:

我不确定在这里处理异步/等待的最佳方法是什么,我的应用程序似乎在调用渲染之前没有等待,所以它试图在数据准备好之前加载。

data.js:

this.asyncFunction = async (x) => { return await _makeRestcall(x) }

this.load = async function(id) {
            this.data = {
                params: await asyncFunction("restCall1").value.reduce( // transform data),
                ideation: await asyncFunction("restCall2").value.reduce( // transform data),
                roles: await asyncFunction("restCall3").value.reduce( // transform data),
                serviceGroups: await asyncFunction("restCall4").value.reduce( // transform data),
                allocationPercents: [],
                maintenanceYears: [0, 3, 5]
            };

            return this.data;
        };

async init() {
    this.d = await this.load();
    console.log("called data async");
}

app.js

import data from 'data'
await data.init();
render()

理想情况下,我希望 data 中的所有调用并行运行,然后在所有调用完成后返回 this.data。

【问题讨论】:

  • Promise.all 是你的朋友。

标签: javascript ecmascript-6 async-await


【解决方案1】:

我为你做了一个小测试。我建议使用 Promise.all,它可以调度两个异步函数,但在每次调度后在同一个地方等待它们而不会阻塞函数。

请看下面的代码:

getFromAPIA();
getFromAPIB();

// A
async function getFromAPIA() {
    console.log('starting A');
    try {
        const [a, b] = await Promise.all([asyncFunction(), asyncFunction()])

        let data = {
            a,
            b,
        }
        console.log('A RES:', data);
        return data;
    } catch (err) {
        return false; // Handle the error here in case the Promise returned a Reject
    }
}

// B
async function getFromAPIB() {
    console.log('starting B');
    try {
        let data = {
            a: await asyncFunction(),
            b: await asyncFunction(),
        }
        console.log('B RES:', data);
        return data;
    } catch (err) {
        return false; // Handle the error here in case the Promise returned a Reject
    }
}

// MIMIC ASYNC
function asyncFunction() {
    return new Promise((res, rej) => {
        setTimeout(() => {
            res('Hello');
        }, 10000)
    })
};

方法 B 基本上是你做的,花了两倍的时间得到响应, 而方法 A 与 Promise.all 一起使用。现在,promise all 将一组 promise 作为参数并返回一个数组,因此您必须知道调度的顺序才能以您想要的方式构造对象。

【讨论】:

  • 如果您可以在 Promise.all() 中添加 .then() 和 .catch() 那就太好了。永远不要让 Promise 未被捕获,如果他想重用您的代码,我认为最好能发现他的错误。
  • 我同意,promise 应该始终包装在 try catch 中或使用 .then 和 .catch 处理。我现在将编辑它。感谢您指出这一点。
【解决方案2】:

我的应用程序在调用渲染之前似乎没有等待,所以它试图在数据准备好之前加载。

你在等待错误的对象,你在等待 Promise.value.reduce

this.asyncFunction = async (x) => { return await _makeRestcall(x) }

this.load = async function(id) {
    this.data = {
        params: (await asyncFunction("restCall1")).value.reduce( // transform data),
        ideation: (await asyncFunction("restCall2")).value.reduce( // transform data),
        roles: (await asyncFunction("restCall3")).value.reduce( // transform data),
        serviceGroups: (await asyncFunction("restCall4")).value.reduce( // transform data),
        allocationPercents: [],
        maintenanceYears: [0, 3, 5]
    };

    return this.data;
};

async init() {
    this.d = await this.load();
    console.log("called data async");
}

【讨论】:

    猜你喜欢
    • 2015-08-15
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    • 2013-05-13
    相关资源
    最近更新 更多