一个接一个地解决承诺(即按顺序)? [英] Resolve promises one after another (i.e. in sequence)?

查看:142
本文介绍了一个接一个地解决承诺(即按顺序)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Consider the following code that reads an array of files in a serial/sequential manner. readFiles returns a promise, which is resolved only once all files have been read in sequence.

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 函数?

The code above code works, but I don't like having to do recursion for things to occur sequentially. Is there a simpler way that this code can be re-written so that I don't have to use my weird readSequential function?

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

Originally I tried to use Promise.all, but that caused all of the readFile calls to happen concurrently, which is not what I want:

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


推荐答案

2017年更新:我如果环境支持它将使用异步函数:

Update 2017: I would use an async function if the environment supports it:

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

如果您愿意,可以推迟阅读文件,直到您需要使用异步生成器(如果您的环境支持它):

If you'd like, you can defer reading the files until you need them using an async generator (if your environment supports it):

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






更新:第二个想法 - 我可能会使用换句话为:


Update: In second thought - I might use a for loop instead:

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
};

在其他承诺库(例如when和Bluebird)中,你有实用的方法。

In other promise libraries (like when and Bluebird) you have utility methods for this.

例如,Bluebird将是:

For example, Bluebird would be:

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.
});

虽然确实没有理由今天使用异步等待。

Although there is really no reason not to use async await today.

这篇关于一个接一个地解决承诺(即按顺序)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆