如何用Q循环调用返回promise Nodejs

如何用Q循环调用返回promise Nodejs

刚刚用Q,不是很熟悉promise的概念。 我有一个事件处理流,传进来的参数有可能是url数组或者是一个url。 如何在参数是一个数组的情况下,循环调用事件处理流的下一步?

function foo(url) {
  var deferred = Q.defer();
  if( Array.isArray(url)) {
    url.forEach(function(u) {
      //无效,无法进入boo
      deferred.resolve(u);
    });
  } else {
     //有效能够进入boo
    deferred.resolve(url);
  }
  return deferred.promise;
}

function boo(s) {
  console.log('in boo');
}

2 回复

要使用 Q 库来处理返回 Promise 的情况,并且在参数为数组时循环调用某个函数,你需要正确地处理每个 URL 的异步操作。以下是如何修改你的代码以实现这一目标:

修改后的代码

var Q = require('q');

// 假设 boo 函数处理每个 URL 并返回一个 Promise
function boo(url) {
  console.log('Processing:', url);
  return Q.delay(1000);  // 模拟异步操作
}

// 处理 URL 或 URL 数组的函数
function processUrls(urlsOrUrl) {
  var deferred = Q.defer();

  if (Array.isArray(urlsOrUrl)) {
    // 如果传入的是数组,则逐个处理每个 URL
    var promises = urlsOrUrl.map(function(url) {
      return boo(url);
    });

    // 等待所有 URL 处理完毕
    Q.all(promises)
      .then(function() {
        deferred.resolve();
      })
      .catch(function(err) {
        deferred.reject(err);
      });
  } else {
    // 如果传入的是单个 URL,则直接处理
    boo(urlsOrUrl)
      .then(function() {
        deferred.resolve();
      })
      .catch(function(err) {
        deferred.reject(err);
      });
  }

  return deferred.promise;
}

// 使用示例
processUrls(['http://example.com', 'http://example.org'])
  .then(function() {
    console.log('All URLs processed successfully.');
  })
  .catch(function(err) {
    console.error('Error processing URLs:', err);
  });

解释

  1. 引入 Q 库:

    var Q = require('q');
    
  2. 定义 boo 函数:

    • boo 函数接收一个 URL 并模拟一个异步操作(这里使用 Q.delay(1000) 来模拟)。
    • 这里假设 boo 返回一个 Promise。
  3. 定义 processUrls 函数:

    • processUrls 函数接受一个参数,该参数可以是单个 URL 或者 URL 数组。
    • 使用 Array.isArray 检查参数类型。
    • 如果参数是数组,使用 .map 方法将每个 URL 映射到 boo 函数调用,并生成一个 Promise 数组。
    • 使用 Q.all 等待所有 Promise 完成。
    • 如果参数是单个 URL,则直接调用 boo 并等待其完成。
  4. 使用示例:

    • 调用 processUrls 并传递一个 URL 数组。
    • 使用 .then.catch 处理成功或失败的情况。

通过这种方式,你可以确保无论传入的是单个 URL 还是多个 URL,都能正确地按顺序处理它们。


为了使用Q库来循环调用返回Promise的情况,你需要确保每个异步操作都正确地解析或拒绝Promise。在这个例子中,你需要为每个URL创建一个单独的Promise,并且等待所有这些Promise完成。这可以通过Q.all方法实现,该方法接受一个Promise数组并返回一个新的Promise,当所有这些Promise都成功完成后,新的Promise才会成功。

以下是修改后的代码示例:

var Q = require('q');

function handleUrl(url) {
  var deferred = Q.defer();
  // 模拟异步操作,例如访问URL
  setTimeout(() => {
    deferred.resolve(`处理了URL: ${url}`);
  }, 1000);
  return deferred.promise;
}

function foo(urls) {
  if (Array.isArray(urls)) {
    // 如果是数组,则对每个URL执行handleUrl函数
    return Q.all(urls.map(handleUrl));
  } else {
    // 如果不是数组,则直接处理单个URL
    return handleUrl(urls);
  }
}

// 使用时:
foo(['http://example.com', 'http://example.org'])
  .then(results => {
    results.forEach(result => {
      console.log(result); // 输出处理过的URL
    });
  })
  .catch(err => {
    console.error('发生错误:', err);
  });

foo('http://example.com')
  .then(result => {
    console.log(result); // 输出单个处理过的URL
  })
  .catch(err => {
    console.error('发生错误:', err);
  });

在这个例子中,handleUrl函数模拟了一个异步操作(比如网络请求),并返回一个Promise。foo函数根据传入的是数组还是单个URL,分别使用Q.all来等待多个Promise完成,或直接返回单个Promise。这样可以确保无论输入是一组URL还是单个URL,都能正确处理。

回到顶部