猿问

如何使可链接的异步函数并行工作,然后只等待最后一个函数?

我想做以下事情:


const contextSeeder = new ContextSeeder(context);

let props = (await (await contextSeeder.withList()).withUser()).get();

但理想情况下,这看起来像:


const contextSeeder = new ContextSeeder(context);

let props = await contextSeeder.withList().withUser().get();

withList()并且withUser()都会进行 API 调用。所以理想情况下它们应该并行运行。他们都修改了类中的一个对象,该对象是返回值(可能存在竞争条件吗?)因此,鉴于我将这两个“加载器”称为“加载器”,我希望它.get()成为实际必须等待的那个。可能吗?因为在第一种方式中,它看起来会一个一个地处理(因为两个调用中的等待)


我在一个内部运行它async function,并且我需要在函数返回时出现这些数据。我不能做一个.then()


谢谢


export default class ContextSeeder {


    context = {};

    serverContext;


    constructor(serverContext = undefined) {

        this.serverContext = serverContext;

    }


    withUser = async (listId = undefined) => {

        let userContext = {};

        await UserContextSeeder(this.serverContext).then(context => {userContext = context});

        this.context = {...this.context, user: userContext}

        return this;

    }


    withList = async (userId = undefined) => {

        let listContext = {};

        await ListContextSeeder(context).then(context => {listContext = context});

        this.context = {...this.context, list: listContext}

        return this;

    }


    get = () => {

        return this.context;

    }

}


牛魔王的故事
浏览 139回答 3
3回答

茅侃侃

如果您想并行运行请求,则在调用 .get() 之前等待它们都完成,您可以尝试使用以下代码Promise.all:// we wait for both promises to finishawait Promise.all([contextSeeder.withList(), contextSeeder.withUser()]);// they're both finished so we can get it nowlet props = contextSeeder.get();

猛跑小猪

以下内容一一开始异步检索,然后使用Promise.all. 最后,将结果解构,然后添加到要返回的对象中。我认为这是对您的代码的简化,因为中间状态不会公开共享。我会重命名ListContextSeeder并UserContextSeeder成为更惯用的东西。大写的名称通常保留给构造函数。export default async function seedContext({ serverContext, listId, userId }) {  const p1 = ListContextSeeder(serverContext, listId)  const p2 = UserContextSeeder(serverContext, userId)  const [list, user] = await Promise.all([p1, p2])  return { list, user }}

千万里不及你

出于此答案的目的,我将忽略您没有使用 userId 或 listId 的事实。您可以使用以下内容简化代码:export default class ContextSeeder {    context = {};    serverContext;    constructor(serverContext = undefined) {        this.serverContext = serverContext;    }    withList = async (listId = undefined) => {        let seededUserContext = await UserContextSeeder(this.serverContext);        this.context = {...this.context, user: seededUserContext}        // Not needed unless you still want to chain them        // return this;    }    withUser = async (userId = undefined) => {        let seededListContext = await ListContextSeeder(context);        this.context = {...this.context, list: seededListContext}        // Not needed unless you still want to chain them        // return this;    }    get = () => {        return this.context;    }}然后,您可以使用 Promise.all() 等待两者的解决:// They now run in "parallel"await Promise.all([contextSeeder.withList(), contextSeeder.withUser());let props = contexSeeder.get();更新根据下面 Ben Aston 的回答,另一个改进是将此行为封装在另一个内部方法中,传递一个中间上下文,并且只有在两个调用都完成后才设置实际上下文。export default class ContextSeeder {  context = {};  serverContext;  constructor(serverContext = undefined) {    this.serverContext = serverContext;  }  withList = async (listId = undefined, intermediateContext) => {    let seededUserContext = await UserContextSeeder(this.serverContext);    // No spread operator needed, just set the property    intermediateContext.user = seededUserContext;    // Not needed unless you still want to chain them    // return this;  };  withUser = async (userId = undefined, intermediateContext) => {    let seededListContext = await ListContextSeeder(context);    // No spread operator needed, just set the property    intermediateContext.list = seededListContext;    // Not needed unless you still want to chain them    // return this;  };  seedContext = async (userId, listId) => {    let intermediateContext = {};    await Promise.all([      withUser(userId, intermediateContext),      withList(listId, intermediateContext)    ]);    this.context = intermediateContext;  }  get = () => {    return this.context;  };}然后,只需等待 seedContext:await contextSeeder.seedContext(userId, listId);let props = contextSeeder.get();
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答