如何在JavaScript中实现更复杂的Promise链?

huangapple go评论67阅读模式
英文:

How can I implement a more complex promise chain in javascript?

问题

我尝试实现一个更复杂的Promise链。流程和依赖关系如下:

  • 启动 A、B 和 D
  • 当 A 和 B 完成时启动 C
  • 当 C 和 D 完成时启动 E

以下是模拟代码:

function test_p(name, sec) {
    console.log(Date.now()-start,'Started ', name, " Sec: ", sec);
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(Date.now()-start,'Resolved ', name, " Sec: ", sec);
            resolve(10);
        }, sec * 1000);
    });
}
start = Date.now(); 
p1 = test_p("A", 2)
    .then((result) => { console.log(Date.now()-start, result); return result });
p2 = test_p("B", 5)
    .then((result) => { console.log(Date.now()-start,result); return result });
pp1 = Promise.all([p1, p2])
    .then((result) => { console.log(Date.now()-start,"p1-p2 started"); return result })
    .then(() => { console.log(Date.now()-start,"p1-p2 done ") })
    .then(() => {
        p3 = test_p("C", 5)
            .then((result) => { console.log(Date.now() - start, result); return result })
    });    
p4 = test_p("D", 7)
    .then((result) => { console.log(Date.now()-start,result); return result });
pp2 = Promise.all([pp1, p3, p4])
    .then((result) => { console.log(Date.now()-start,"pp1-p4 started"); return result });

这是控制台输出:0 'Started ' 'A' ' Sec: ' 2 VM10447:2 2
'Started ' 'B' ' Sec: ' 5 VM10447:2 2 'Started ' 'D' ' Sec: ' 7
Promise {} VM10447:5 2001 'Resolved ' 'A' ' Sec: ' 2
VM10489:3 2001 10 VM10447:5 5003 'Resolved ' 'B' ' Sec: ' 5 VM10489:5
5003 10 VM10489:7 5003 'p1-p2 started' VM10489:8 5003 'p1-p2 done '
VM10447:2 5003 'Started ' 'C' ' Sec: ' 5 VM10447:5 7002 'Resolved '
'D' ' Sec: ' 7 VM10489:14 7003 10 VM10489:16 7003 'pp1-p4 started'
VM10447:5 10004 'Resolved ' 'C' ' Sec: ' 5 VM10489:11 10004 10

我希望第二个Promise.all在C解决后大约在10000毫秒触发。

英文:

I try to implement a more complex promise chain.
Flow and dependencies:

  • Start A, B and D
  • Start C when A and B are done
  • Start E when C and D are done

Here the simulation code:

function test_p(name, sec) {
    console.log(Date.now()-start,'Started ', name, " Sec: ", sec);
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(Date.now()-start,'Resolved ', name, " Sec: ", sec);
            resolve(10);
        }, sec * 1000);
    });
}
start = Date.now(); 
p1 = test_p("A", 2)
    .then((result) => { console.log(Date.now()-start, result); return result });
p2 = test_p("B", 5)
    .then((result) => { console.log(Date.now()-start,result); return result });
pp1 = Promise.all([p1, p2])
    .then((result) => { console.log(Date.now()-start,"p1-p2 startet"); return result })
    .then(() => { console.log(Date.now()-start,"p1-p2 done ") })
    .then(() => {
        p3 = test_p("C", 5)
            .then((result) => { console.log(Date.now() - start, result); return result })
    });    
p4 = test_p("D", 7)
    .then((result) => { console.log(Date.now()-start,result); return result });
pp2 = Promise.all([pp1, p3, p4])
    .then((result) => { console.log(Date.now()-start,"pp1-p4 startet"); return result });

> This is the console protocol: 0 'Started ' 'A' ' Sec: ' 2 VM10447:2 2
> 'Started ' 'B' ' Sec: ' 5 VM10447:2 2 'Started ' 'D' ' Sec: ' 7
> Promise {<pending>} VM10447:5 2001 'Resolved ' 'A' ' Sec: ' 2
> VM10489:3 2001 10 VM10447:5 5003 'Resolved ' 'B' ' Sec: ' 5 VM10489:5
> 5003 10 VM10489:7 5003 'p1-p2 startet' VM10489:8 5003 'p1-p2 done '
> VM10447:2 5003 'Started ' 'C' ' Sec: ' 5 VM10447:5 7002 'Resolved '
> 'D' ' Sec: ' 7 VM10489:14 7003 10 VM10489:16 7003 'pp1-p4 startet'
> VM10447:5 10004 'Resolved ' 'C' ' Sec: ' 5 VM10489:11 10004 10

I wanted the second Promise.all to fire after C resolved around 10000 msec

答案1

得分: 1

你当前代码的问题在于 `pp1` 中最后一个 `.then()` 调用没有返回 `p3`因此你启动了计时器 C但从未将其作为 `pp1` 的依赖项要修复它只需在那个 `.then()` 中返回 `p3`如下所示

```js
pp1 = Promise.all([p1, p2])
    .then((result) => { console.log(Date.now()-start,"p1-p2 startet"); return result })
    .then(() => { console.log(Date.now()-start,"p1-p2 done ") })
    .then(() => {
        p3 = test_p("C", 5)
            .then((result) => { console.log(Date.now() - start, result); return result })
        return p3;
    }); 

然而,你的整体代码可以被极大地简化,并提高可读性,如下所示:

const start = Date.now();

async function delay(name, timeInSec) {
	return new Promise((res) => setTimeout(res, timeInSec * 1000)).then(() =>
		console.log(name, Date.now() - start)
	);
}

console.log("start:", start);
const A = delay("A", 2);
const B = delay("B", 5);
const D = delay("D", 7);

const ABC = Promise.all([A, B]).then(() => delay("C", 5));

const CDE = Promise.all([ABC, D]).then(() => delay("E", 2));

<details>
<summary>英文:</summary>

The issue your current code is that the last `.then()` call in `pp1` doesn&#39;t return `p3`. As a result, you start timer C, but you never make it a dependency of `pp1`. So to fix it, simply return `p3` inside that `.then()`, like so:
```js
pp1 = Promise.all([p1, p2])
    .then((result) =&gt; { console.log(Date.now()-start,&quot;p1-p2 startet&quot;); return result })
    .then(() =&gt; { console.log(Date.now()-start,&quot;p1-p2 done &quot;) })
    .then(() =&gt; {
        p3 = test_p(&quot;C&quot;, 5)
            .then((result) =&gt; { console.log(Date.now() - start, result); return result })
        return p3;
    }); 

However, your code overall can be immensely simplified and improved for readability like so:

const start = Date.now();

async function delay(name, timeInSec) {
	return new Promise((res) =&gt; setTimeout(res, timeInSec * 1000)).then(() =&gt;
		console.log(name, Date.now() - start)
	);
}

console.log(&quot;start:&quot;, start);
const A = delay(&quot;A&quot;, 2);
const B = delay(&quot;B&quot;, 5);
const D = delay(&quot;D&quot;, 7);

const ABC = Promise.all([A, B]).then(() =&gt; delay(&quot;C&quot;, 5));

const CDE = Promise.all([ABC, D]).then(() =&gt; delay(&quot;E&quot;, 2));

huangapple
  • 本文由 发表于 2023年5月28日 21:54:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76351833.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定