javascript 我怎样才能以正确的方式安排不同承诺的执行流程以获得结果?

brccelvz  于 2023-02-28  发布在  Java
关注(0)|答案(4)|浏览(116)

承诺链执行流程

const timeoutPromise = (interval, intervalName) => {
  return new Promise((resolve, reject) => {
    setTimeout(function(){
      console.log(`Executed ${intervalName} at: ${new Date().toString()} with interval of ${interval}`);
      resolve();
    }, interval);
  });
};
let main = () => {
  console.log('Starting at:', new Date().toString());

  console.log('Completed at:', new Date().toString());
};

从上面给出的图像中,创建一个以2个字段为参数的函数:- 一个字母(在我们的情况下,A、B、C、D)- 以毫秒为单位的时间将是您提供的任何不同值
在函数内部,必须有一个setTimeout,其值为上述时间
主函数将开始执行,使得上述创建的函数将按照上述指定的时间顺序执行,即:- A & D会一起开始- C只有在A & D完成后才开始- B将在A完成后立即开始
执行方式必须:- 程序执行开始时,应在控制台中记录时间和消息- 当程序执行结束时,应在控制台中记录时间和消息- 每次调用该函数时都应记录时间和字母
我尝试了所有可能的方法,但要么函数A运行了两次,要么B在程序执行结束后被记录...

vaj7vani

vaj7vani1#

要按特定顺序解决承诺,您需要相应地链接它们。以下是其中一种方法的细分:
1.由于AD可以立即启动,我们调用timeoutPromise函数并将返回的promise保存在变量中,以便稍后引用它们。
1.由于我们需要在A解析后立即启动B,因此可以在变量中保存对A承诺的引用,以便在A完成时启动B
1.我们可以使用Promise.all来等待AD都解析好,然后再启动C

  1. Promise.all用于等待BC承诺稳定,以确保在我们结束执行之前两个承诺都已稳定。

运行示例:

const timeoutPromise = (seconds, intervalName) => {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      console.log(
        `Executed ${intervalName} at: ${new Date().toString()} with interval of ${seconds} seconds`
      );
      resolve();
    }, seconds * 1000);
  });
};

let main = () => {
  console.log('Starting at:', new Date().toString());

  const promiseA = timeoutPromise(1, 'A');
  const promiseAandD = Promise.all([promiseA, timeoutPromise(4, 'D')]);

  const promiseBThen = promiseA.then(() => timeoutPromise(1, 'B'));
  const promiseCThen = promiseAandD.then(() => timeoutPromise(1, 'C'));

  Promise.all([promiseCThen, promiseBThen]).then(
    () => {
      console.log('Completed at:', new Date().toString());
    }
  );
};

main();
5lhxktic

5lhxktic2#

使用setTimeout很可能不是安排一系列承诺的最佳方法,下面是一个不同的方法,它使用async函数来帮助澄清执行顺序:

// helper function to create a promise:
function prom(name,delay){
  return new Promise((res,rej)=>{
  setTimeout(()=>{
   console.log(`promise ${name}: ${delay}ms`);
   res(name)}, delay);
});
}

async function main(){
 let [d,a]=await Promise.all([prom("D",400),prom("A",200)]);
 let [c,b]=await Promise.all([prom("C",300),prom("B",100)]);
 console.log(`all done: ${[a,b,c,d].join(", ")}`)
}

main()

一开始,承诺D和A是并行等待的。一旦它们实现了,承诺C和B也是并行等待的。诚然,承诺B可以开始得稍微早一点,因为它不依赖于D的实现,但这最终不会真正产生显著的差异。而且,为了代码易于阅读和理解,我认为这种解决方案是足够的。

    • 更新**

好的,这里是另一个版本--稍微有点难读--它允许D和B部分并行运行(B可以在A解决后启动):
x一个一个一个一个x一个一个二个x
不要被脚本末尾的await Aawait D所迷惑:由于这两个承诺都已经解决,这里不再需要额外的"等待"时间,需要await来访问承诺ad返回的数据。

5t7ly7z5

5t7ly7z53#

一些可怕的职位在这里🙃
work下面是一个生成承诺值的通用函数。请将work替换为任何生成承诺的函数。run编码依赖关系图-

const work = value =>
  new Promise(r => setTimeout(r, 1000, value))

async function run() {
  const [a,d] = await Promise.all([work("A"), work("D")])
  const ctask = work(a + d + "->C")
  const btask = work(a + "->B")
  return Promise.all([ctask, btask])
}

run().then(console.log).catch(console.error)
nbysray5

nbysray54#

除了优萨夫的回答,这里还有一个概括性的尝试,让术语“任务”表示一个返回承诺的函数。

class Task {
  constructor(task) {
    this.task = task;
    this.prereqs = [];
    this.succcnt = 0;
  }
  after(p) {
    this.prereqs.push(p);
    p.succcnt++;
  }
}
class Tasks {
  tasks = [];
  add(task) {
    var p = new Task(task);
    this.tasks.push(p);
    return p;
  }
  execute() {
    var tasks = [];
    while (tasks.length < this.tasks.length) {
      var l = tasks.length;
      this.tasks.filter(q => q.succcnt === 0).forEach(function(p) {
        tasks.unshift(p);
        for (var q of p.prereqs) q.succcnt--;
        p.succcnt = -1;
      });
      if (tasks.length === l)
        return Promise.reject("cyclic dependencies");
    }
    for (var p of tasks)
      p.task = Promise.all(p.prereqs.map(q => q.task)).then(p.task);
    return Promise.all(this.tasks.map(q => q.task));
  }
}

可以将单个任务add艾德到Tasks示例中,并为它们所依赖的每个其他任务调用它们的after方法。然后,Tasks示例的execute方法按必要的顺序执行所有任务(如果它能找到一个,即除非存在循环依赖关系)。

function makePromise(x) {
  return new Promise(function(resolve, reject) {
    console.log(x, "starts");
    setTimeout(function() {
      console.log(x, "ends");
      resolve(x);
    }, 1000);
  });
}
var p = new Tasks();
var A = p.add(() => makePromise("A"));
var B = p.add(() => makePromise("B"));
var C = p.add(() => makePromise("C"));
var D = p.add(() => makePromise("D"));
B.after(A);
C.after(A);
C.after(D);
p.execute().then(console.log);

相关问题