Spec-Zone.ru › Bluebird

Promise.map

Promise.map(
    Iterable<any>|Promise<Iterable<any>> input,
    function(any item, int index, int length) mapper,
    [Object {concurrency: int=Infinity} options]
) -> Promise

Для конечной Iterable(массивы являются Iterable), или обещания конечного Iterable, которое возвращает обещания (или смесь обещаний и значений), итерируется по всем значениям в Iterable в массив и преобразует этот массив в другой с помощью заданной mapper функции.

Обещания, возвращаемые функцией mapper , ожидают выполнения, и возвращаемое обещание не выполняется, пока все преобразованные обещания не будут выполнены. Если любое обещание в массиве отклонено, или любое обещание, возвращаемое функцией mapper , отклонено, возвращаемое обещание также отклоняется.

Функция-преобразователь для данного элемента вызывается как можно скорее, то есть, когда обещание для индекса этого элемента в входном массиве выполнено. Это не означает, что элементы в результирующем массиве будут в случайном порядке, это означает, что .map может быть использован для координации конкурентности в отличие от .all.

Распространённое применение Promise.map - замена шаблонного кода .push+Promise.all:

var promises = [];
for (var i = 0; i < fileNames.length; ++i) {
    promises.push(fs.readFileAsync(fileNames[i]));
}
Promise.all(promises).then(function() {
    console.log("done");
});

// Using Promise.map:
Promise.map(fileNames, function(fileName) {
    // Promise.map awaits for returned promises as well.
    return fs.readFileAsync(fileName);
}).then(function() {
    console.log("done");
});

// Using Promise.map and async/await:
await Promise.map(fileNames, function(fileName) {
    // Promise.map awaits for returned promises as well.
    return fs.readFileAsync(fileName);
});
console.log("done");

Более сложный пример:

var Promise = require("bluebird");
var join = Promise.join;
var fs = Promise.promisifyAll(require("fs"));
fs.readdirAsync(".").map(function(fileName) {
    var stat = fs.statAsync(fileName);
    var contents = fs.readFileAsync(fileName).catch(function ignore() {});
    return join(stat, contents, function(stat, contents) {
        return {
            stat: stat,
            fileName: fileName,
            contents: contents
        }
    });
// The return value of .map is a promise that is fulfilled with an array of the mapped values
// That means we only get here after all the files have been statted and their contents read
// into memory. If you need to do more operations per file, they should be chained in the map
// callback for concurrency.
}).call("sort", function(a, b) {
    return a.fileName.localeCompare(b.fileName);
}).each(function(file) {
    var contentLength = file.stat.isDirectory() ? "(directory)" : file.contents.length + " bytes";
    console.log(file.fileName + " last modified " + file.stat.mtime + " " + contentLength)
});

Опция Map: concurrency

Вы можете необязательно указать предел конкурентности:

...map(..., {concurrency: 3});

Предел конкурентности относится к обещаниям, возвращаемым функцией-преобразователем, и фактически ограничивает количество созданных обещаний. Например, если concurrency равно 3 , а обратный вызов-преобразователь был вызван достаточно раз, так что в настоящее время ожидаются три возвращаемых обещания, дальнейшие вызовы не происходят, пока одно из ожидающих обещаний не разрешится. Таким образом, функция-преобразователь будет вызвана три раза, и она будет вызвана снова только после того, как по крайней мере одно из обещаний разрешится.

Рассмотрим пример с и без ограничений, и посмотрим, как это влияет на время чтения 20 файлов:

var Promise = require("bluebird");
var join = Promise.join;
var fs = Promise.promisifyAll(require("fs"));
var concurrency = parseFloat(process.argv[2] || "Infinity");
console.time("reading files");
fs.readdirAsync(".").map(function(fileName) {
    var stat = fs.statAsync(fileName);
    var contents = fs.readFileAsync(fileName).catch(function ignore() {});
    return join(stat, contents, function(stat, contents) {
        return {
            stat: stat,
            fileName: fileName,
            contents: contents
        }
    });
// The return value of .map is a promise that is fulfilled with an array of the mapped values
// That means we only get here after all the files have been statted and their contents read
// into memory. If you need to do more operations per file, they should be chained in the map
// callback for concurrency.
}, {concurrency: concurrency}).call("sort", function(a, b) {
    return a.fileName.localeCompare(b.fileName);
}).then(function() {
    console.timeEnd("reading files");
});
$ sync && echo 3 > /proc/sys/vm/drop_caches
$ node test.js 1
reading files 35ms
$ sync && echo 3 > /proc/sys/vm/drop_caches
$ node test.js Infinity
reading files: 9ms

Порядок, в котором map вызывает функцию-преобразователь для элементов массива, не определён, нет гарантий относительно порядка выполнения map для элементов. Для гарантии порядка в последовательном выполнении см. Promise.mapSeries.

© 2013–2018 Petka Antonov
Licensed under the MIT License.
http://bluebirdjs.com/docs/api/promise.map.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API