Skip to content

xswei/d3-queue

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 

Repository files navigation

d3-queue

queue 通过可配置的并发来执行 0 个或多个延迟的异步任务: 你可以控制同时进行多少个任务。当所有的任务完成或其中一个出错时候,队列会将结果传递给 await 回调。这个模块类似于Async.jsparallel(并行执行) (当 concurrencyinfinite 时),series (当 concurrency 为 1 时),以及 queue,但是此模块占用空间更小: 从版本 2 起,d3-queue 在压缩后大概有 700 字节,而 Async 库却达到 4300。

每个任务被定义为将回调作为最后一个参数的函数。例如,下面为一个延时打印 hello! 的例子:

function delayedHello(callback) {
  setTimeout(function() {
    console.log("Hello!");
    callback(null);
  }, 250);
}

当任务完成时,必须调用指定的回调。回调的第一个参数为 null (如果任务成功的话,否则为 error), 可选的第二个参数为任务的返回值(如果任务有多个返回值要将其包装在对象或数组中)。

要同时运行多个任务,则要创建一个队列,使用 defer 加入任务,然后注册一个 await 回调用来在所有任务完成或有任务出错时候执行:

var q = d3.queue();
q.defer(delayedHello);
q.defer(delayedHello);
q.await(function(error) {
  if (error) throw error;
  console.log("Goodbye!");
});

当然你也可以使用 for 循环来加入多个任务:

var q = d3.queue();

for (var i = 0; i < 1000; ++i) {
  q.defer(delayedHello);
}

q.awaitAll(function(error) {
  if (error) throw error;
  console.log("Goodbye!");
});

任务可以配置可选的参数,比如为延时打印的任务传入自定义参数:

function delayedHello(name, delay, callback) {
  setTimeout(function() {
    console.log("Hello, " + name + "!");
    callback(null);
  }, delay);
}

在使用 queue.defer 添加任务时,只需要将需要的参数传入 defer 即可。defer 会将参数传入指定的任务函数。你亦可以使用链式调用以避免创建本地变量:

d3.queue()
    .defer(delayedHello, "Alice", 250)
    .defer(delayedHello, "Bob", 500)
    .defer(delayedHello, "Carol", 750)
    .await(function(error) {
      if (error) throw error;
      console.log("Goodbye!");
    });

asynchronous callback pattern(异步回调模型) 在 Node.js 中很常见,因此 d3-queue 可以直接与很多 Node APIs 协同工作。比如,并发获取stat two files(两个文件信息):

d3.queue()
    .defer(fs.stat, __dirname + "/../Makefile")
    .defer(fs.stat, __dirname + "/../package.json")
    .await(function(error, file1, file2) {
      if (error) throw error;
      console.log(file1, file2);
    });

你也可以将任务中断: 在定义任务队列时会返回一个带有 abort 方法的对象。因此,如果一个任务在开始时调用了 setTimeout,则中断时会执行 clearTimeout 来取消任务。例如:

function delayedHello(name, delay, callback) {
  var id = setTimeout(function() {
    console.log("Hello, " + name + "!");
    callback(null);
  }, delay);
  return {
    abort: function() {
      clearTimeout(id);
    }
  };
}

当调用 queue.abort 时,任何正在进行的任务会被立即停止,还未开始的任务不会启动。要注意的是你可以使用 queue.abort 终止但不取消任务,这种情况下未启动的任务被取消,但是已经执行的任务还会继续执行。比较方便的是 d3-request 库实现了 XMLHttpRequest 的终止。比如:

var q = d3.queue()
    .defer(d3.request, "http://www.google.com:81")
    .defer(d3.request, "http://www.google.com:81")
    .defer(d3.request, "http://www.google.com:81")
    .awaitAll(function(error, results) {
      if (error) throw error;
      console.log(results);
    });

取消这些任务,调用 q.abort() 即可.

Installing

NPM: npm install d3-queue. Bower: bower install d3-queue. 也可以下载 latest release. 可以直接从 d3js.orgstandalone library 或作为 D3 4.0 的一部分直接载入. 支持 AMD, CommonJS 以及基本的标签引入形式,如果使用标签引入则会暴露 d3 全局变量:

<script src="https://d3js.org/d3-queue.v3.min.js"></script>
<script>

var q = d3.queue();

</script>

在浏览器中测试 d3-queue.

API Reference

# d3.queue([concurrency]) <>

使用指定的 concurrency 创建一个新的队列。如果没有指定 concurrency 则表示队列并发数为无穷大。此外 concurrency 必须为一个正整数。例如,如果 concurrency 为 1,则所有的任务会依次执行。如果 concurrency 为 3 则最多同时并发执行 3 个任务。当在 web 浏览器中加载资源时时非常有用的。

# queue.defer(task[, arguments…]) <>

将指定的异步 task 添加到队列中,可以指定可选的 argumentstask 为一个函数以在任务开始执行时调用。它会将可选的参数以及外加一个 callback 传递给 task 函数,task 函数可以使用这些可选参数并在完成时自动调用 callback 。注意在添加任务的时候不需要指定 callback 只需要指定可选参数即可, callback 最后最后一个参数定义在具体的 task 函数中。在 task 中调用 callback 时候必须传入的第一个参数为 errornull 以表示任务是否成功执行。第二个参数可选,为任务的返回结果(多个返回结果时需要包装)。

例如,下面有一个简单的延时返回计算结果的任务:

function simpleTask(callback) {
  setTimeout(function() {
    callback(null, {answer: 42});
  }, 250);
}

如果任务出错,则后续的未执行的任务将不会被执行。对于并发数为 1 的序列队列来说,这意味着某个任务只有在前序所有任务成功执行后才会执行。对于并发数高的队列来说,第一次出现任务出错就会将其报告给 await 回调,此时已经执行的任务会继续执行但是结果不会报告给 await 回调。

任务只能在queue.awaitqueue.awaitAll 之前被添加到队列中。如果一个任务在其之后添加,则会抛出错误。如果 task 不是函数则也会抛出错。

# queue.abort() <>

中断活动的任务,并调用活动任务的 task.abort 方法(如果有的话)。这个方法会阻止新的任务的执行,并立即调用queue.awaitqueue.awaitAll 回调并传递任务终止的错误表示。参考任务终止的实现介绍。请注意如果你的任务不可终止,即使已经调用了 await 回调,已经运行的任务会继续执行。await 回调只会在终止时候调用一次,随后任务完成或失败都不会再次触发 await 回调。

# queue.await(callback) <>

设置所有任务完成时需要调用的 callback . 回调的第一个参数为 error (如果出错的话),否则为 null。如果任务出错,则不会有其他的附加参数传递给 callback。除此之外,回调会依次传入每个任务的返回结果作为参数。例如:

d3.queue()
    .defer(fs.stat, __dirname + "/../Makefile")
    .defer(fs.stat, __dirname + "/../package.json")
    .await(function(error, file1, file2) { console.log(file1, file2); });

如果所有 deferred 任务都完成,则 callback 会立即执行。这个方法只能被调用一次,也就是只能使用一次 queue.await,如果多次指定 await 回调或在 queue.awaitAll 之后再次指定 await 回调则会抛出错误。如果 cabblack 不是一个函数也会抛出错误。

# queue.awaitAll(callback) <>

设置所有任务完成时执行的 callbackcallback 的第一个参数为 error (如果有错误发生的话) 或者 null (没有出错)。如果出错的话 callback 不会再有其他的参数。此外,所有任务的返回结果会以数组的形式作为 callback 的第二参数传递。例如:

d3.queue()
    .defer(fs.stat, __dirname + "/../Makefile")
    .defer(fs.stat, __dirname + "/../package.json")
    .awaitAll(function(error, files) { console.log(files); });

如果所有 deferred 的任务都完成则会立即调用 callback。这个方法只能被调用一次,也就是只能指定一次 queue.awaitAll. 如果在 queue.await 之后再次调用或者多次调用都会抛出错误,如果 callback 不是函数类型也会抛出错误提示。

About

d3-queue 中文

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published