当前位置: 首页 > 面试题库 >

解决承诺一个接一个(即按顺序)?

宦炜
2023-03-14
问题内容

考虑以下以串行/顺序方式读取文件数组的代码。readFiles返回一个promise,仅当依次读取所有文件后,promise才会解析。

var readFile = function(file) {
  ... // Returns a promise.
};

var readFiles = function(files) {
  return new Promise((resolve, reject) =>

    var readSequential = function(index) {
      if (index >= files.length) {
        resolve();
      } else {
        readFile(files[index]).then(function() {
          readSequential(index + 1);
        }).catch(reject);
      }
    };

   readSequential(0); // Start!

  });
};

上面的代码有效,但是我不喜欢必须递归使事情顺序发生。有没有更简单的方法可以重写此代码,这样我就不必使用怪异的readSequential函数了?

最初我尝试使用Promise.all,但是这导致所有readFile调用同时发生,这 不是 我想要的:

var readFiles = function(files) {
  return Promise.all(files.map(function(file) {
    return readFile(file);
  }));
};

问题答案:

2017年更新 :如果环境支持,我将使用异步功能:

async function readFiles(files) {
  for(const file of files) {
    await readFile(file);
  }
};

如果需要,可以使用异步生成器(如果您的环境支持)将读取文件的时间推迟到需要它们之前:

async function* readFiles(files) {
  for(const file of files) {
    yield await readFile(file);
  }
};

更新:再次考虑-我可能改用for循环:

var readFiles = function(files) {
  var p = Promise.resolve(); // Q() in q

  files.forEach(file =>
      p = p.then(() => readFile(file)); 
  );
  return p;
};

或更紧凑,减少:

var readFiles = function(files) {
  return files.reduce((p, file) => {
     return p.then(() => readFile(file));
  }, Promise.resolve()); // initial
};

在其他Promise库(如when和Bluebird)中,您可以使用此方法。

例如,蓝鸟将是:

var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));

var readAll = Promise.resolve(files).map(fs.readFileAsync,{concurrency: 1 });
// if the order matters, you can use Promise.each instead and omit concurrency param

readAll.then(function(allFileContents){
    // do stuff to read files.
});

尽管今天确实没有理由 使用异步等待。



 类似资料:
  • 考虑以下以串行/顺序方式读取文件数组的代码。返回一个promise,该promise仅在按顺序读取所有文件后才解析。 上面的代码可以工作,但我不喜欢必须为事情按顺序发生而做递归。有没有更简单的方法可以重写这段代码,使我不必使用我怪异的函数? 最初,我尝试使用,但这导致所有调用并发发生,这不是我想要的:

  • 问题内容: 我要兑现一个承诺。关键是我真的想在第一个诺言兑现后立即访问(仍在等待中的)第二个 诺言 。不幸的是,当两个诺言都实现时,我似乎只能获得第二个诺言的解决值。 这是我想到的用例: 该功能显示文件选择器,用户可以在其中从自己的硬盘驱动器或URL中选择文件。它返回一个承诺,该承诺将在用户选择文件后立即兑现。此时,我们可能仍然必须通过网络下载所选文件。因此,我不能将所选文件作为分辨率值。相反,应

  • 问题内容: 我必须做一个序列的承诺:我一次只有1个网址,这意味着只有1个诺言。每次我收到一个json时,其中一个都包含另一个json的网址,因此我必须做出另一个承诺。 我可以处理多个诺言,但是在这种情况下,我做不到,因为我没有所有的URL,只有一个。 这个例子不起作用,全部冻结。 问题答案: 您可以使用递归

  • 问题内容: 我有一个整数id的数组,例如 并且我需要为每个ID执行异步远程调用。每个调用都是一个使用$ resource执行的WebAPI请求,并显示为Promise。 我需要创建一个接受这些ID数组的函数,然后初始化递归承诺链。该链应导致对每个ID依次进行webapi调用。这些调用不应并行,而应链接在一起。 有问题的函数返回自己一个“主要”的承诺,该承诺应根据异步Web调用的结果来解决或拒绝。也

  • 假设我在Hadoop环境中资源有限,我不想安排长时间运行的作业(即需要几天时间才能完成)。我正在分析大量过去的时间序列数据。我想安排一次需要一天数据的mapreduce作业(这需要一个小时来处理)。 那么,我如何安排,使新的工作提交后,前一个工作完成?

  • 问题内容: 我对诺言不太熟悉。我想从承诺电话中隐藏承诺的实现。 例: 然后我将在同一文件中而不是在同一函数中解决我的诺言,我称其为诺言。 现在,我知道“ promiseFriend”是不确定的。我如何才能将承诺电话与承诺解决方案区分开? 问题答案: 如果要在函数中定义一个promise并在其他地方使用它,则首先需要从该函数返回promise,而您在代码中没有这样做。然后,您需要实际调用您也没有执行