为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

牛魔王的故事 2022-07-01 16:57:09
我想做以下事情: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;    }}
查看完整描述

3 回答

?
茅侃侃

TA贡献1842条经验 获得超21个赞

如果您想并行运行请求,则在调用 .get() 之前等待它们都完成,您可以尝试使用以下代码Promise.all:


// we wait for both promises to finish

await Promise.all([contextSeeder.withList(), contextSeeder.withUser()]);

// they're both finished so we can get it now

let props = contextSeeder.get();


查看完整回答
反对 回复 2022-07-01
?
猛跑小猪

TA贡献1858条经验 获得超8个赞

以下内容一一开始异步检索,然后使用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 }

}


查看完整回答
反对 回复 2022-07-01
?
千万里不及你

TA贡献1784条经验 获得超9个赞

出于此答案的目的,我将忽略您没有使用 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();


查看完整回答
反对 回复 2022-07-01
  • 3 回答
  • 0 关注
  • 97 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号