【问题标题】:Combining async/await with setTimeout function将 async/await 与 setTimeout 函数相结合
【发布时间】:2018-07-18 22:37:56
【问题描述】:

我正在尝试从网站下载文件,并希望使用 setTimeout 在每个请求之间暂停代码 1 秒。

我有一个 stockFile 函数,它循环遍历一组 url(path 是我在磁盘上存储文件的位置)。这是我的代码(版本 A):

async function stockFiles(urls, path) {
  _.map(urls, async (elem) => {
    await timeOut(1000);
    const writableStream = await _createWriteStream(path);
    await _getFile(elem, writableStream);
  });
}

function timeOut(ms) {
  return new Promise((fulfill) => {
    setTimeout(fulfill, ms);
  });
}

编辑:版本 B:

async function stockFiles(urls, path) {
  _.map(urls, async (elem) => {
    const writableStream = await _createWriteStream(path);
    await _getFile(elem, writableStream);
    await timeOut(1000);
  });
}

function timeOut(ms) {
  return new Promise((fulfill) => {
    setTimeout(fulfill, ms);
  });
}

问题:当我调用 stockFiles(版本 A)时,它会在发出请求之前暂停,但似乎我同时在磁盘上收到所有文件。我真正想要的是我的代码在每个请求之间暂停,因此每个文件接收之间存在延迟。

编辑:当我调用 stockFiles(版本 B)时,它根本不会暂停执行,并且我会同时收到所有文件。

/**************** helpers functions **************/

function _createWriteStream(path) {
  return new Promise((fulfill, reject) => {
    fs.createWriteStream(path, (err, data) => {
      if (err) {
        reject(err);
      }
      fulfill(data);
    });
  });
}

// I use superagent package to make the request
async function _getFile(url, writableStream) {
  await request
    .get(url)
    .buffer(true).parse(request.parse.image)
    .pipe(writableStream);
}

【问题讨论】:

  • 要一次处理一个 Promise,请查看 npm 模块 p-each-series

标签: node.js asynchronous async-await settimeout es6-promise


【解决方案1】:

问题是您同时启动所有请求,然后它们都在等待 1000 毫秒,然后它们都在执行。听起来你已经明白了。您需要做的是将它们排队,以便每个仅在前一个完成后才开始。

尝试将您的 stockFiles 函数更改为类似这样的功能:

async function stockFiles(urls, path) {
  for (let url of urls) {
    const writableStream = await _createWriteStream(path);
    await _getFile(elem, writableStream);
    await timeOut(1000);
  }
}

这是一些完整的示例代码。我已经对其进行了测试,并观察到循环每秒只运行一次迭代(通过观察 console.logs 可以看出)。

function timeOut(ms) {
  return new Promise((fulfill) => {
    setTimeout(fulfill, ms);
  });
}

async function stockFiles(urls, path) {
  for (let url of urls) {
    console.log(url);
    await timeOut(1000);
  }
}

let urls = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
stockFiles(urls);

【讨论】:

  • 我已经尝试过你的建议,但它对我不起作用,现在执行根本不会暂停......(如果我在超时之前添加一个 console.log('hello') ,我看到它们立即在终端上打印,并且一次完成)
  • @ConstanceG 我添加了一些完整的可执行示例代码,希望对您有所帮助。如果您将 console.log 替换为您希望每秒只运行一次的代码,那么您应该很高兴。如果您等待放在那里的代码,那么总等待时间应该是一秒加上该代码异步完成所需的时间。
  • 是的,这正是我尝试过的,不幸的是,这段代码根本没有暂停执行......
猜你喜欢
  • 2016-01-22
  • 2021-12-08
  • 1970-01-01
  • 2018-09-23
  • 2021-12-15
  • 1970-01-01
  • 2016-12-03
相关资源
最近更新 更多