2013-10-17 25 views
17

Tôi hiện đang học cách sử dụng những lời hứa trong nodejsPromises với fs và bluebird

để thử thách đầu tiên của tôi là liệt kê các file trong một thư mục và sau đó nhận được nội dung của mỗi với cả hai bước sử dụng chức năng không đồng bộ. Tôi đã đưa ra các giải pháp sau đây nhưng có một cảm giác mạnh mẽ rằng đây không phải là cách thanh lịch nhất để làm điều này, đặc biệt là phần đầu tiên mà tôi đang "chuyển" các phương pháp không đồng bộ vào những lời hứa

// purpose is to get the contents of all files in a directory 
// using the asynchronous methods fs.readdir() and fs.readFile() 
// and chaining them via Promises using the bluebird promise library [1] 
// [1] https://github.com/petkaantonov/bluebird 

var Promise = require("bluebird"); 
var fs = require("fs"); 
var directory = "templates" 

// turn fs.readdir() into a Promise 
var getFiles = function(name) { 
    var promise = Promise.pending(); 

    fs.readdir(directory, function(err, list) { 
     promise.fulfill(list) 
    }) 

    return promise.promise; 
} 

// turn fs.readFile() into a Promise 
var getContents = function(filename) { 
    var promise = Promise.pending(); 

    fs.readFile(directory + "/" + filename, "utf8", function(err, content) { 
     promise.fulfill(content) 
    }) 

    return promise.promise 
} 

Bây giờ chuỗi cả hứa hẹn:

getFiles() // returns Promise for directory listing 
.then(function(list) { 
    console.log("We got " + list) 
    console.log("Now reading those files\n") 

    // took me a while until i figured this out: 
    var listOfPromises = list.map(getContents) 
    return Promise.all(listOfPromises) 

}) 
.then(function(content) { 
    console.log("so this is what we got: ", content) 
}) 

Như tôi đã viết ở trên, nó trả về kết quả mong muốn, nhưng tôi khá chắc chắn có cách thanh lịch hơn.

Trả lời

43

Mã này có thể được thực hiện ngắn hơn bằng cách sử dụng generic promisification.map phương pháp:

var Promise = require("bluebird"); 
var fs = Promise.promisifyAll(require("fs")); //This is most convenient way if it works for you 
var directory = "templates"; 

var getFiles = function() { 
    return fs.readdirAsync(directory); 
}; 
var getContent = function (filename) { 
    return fs.readFileAsync(directory + "/" + filename, "utf8"); 
}; 

getFiles().map(function (filename) { 
    return getContent(filename); 
}).then(function (content) { 
    console.log("so this is what we got: ", content) 
}); 

Trong thực tế, bạn có thể cắt này hơn nữa kể từ khi chức năng này không kéo trọng lượng của họ nữa:

var Promise = require("bluebird"); 
var fs = Promise.promisifyAll(require("fs")); //This is most convenient way if it works for you 
var directory = "templates"; 

fs.readdirAsync(directory).map(function (filename) { 
    return fs.readFileAsync(directory + "/" + filename, "utf8"); 
}).then(function (content) { 
    console.log("so this is what we got: ", content) 
}); 

.map nên là phương pháp bánh mì và bơ của bạn khi làm việc với các bộ sưu tập - nó thực sự mạnh mẽ vì nó hoạt động cho bất cứ điều gì từ một lời hứa cho một loạt các lời hứa rằng bản đồ để tiếp tục hứa hẹn cho bất kỳ kết hợp trực tiếp valu es ở giữa.

+2

Tốt, cũng để chỉ ra cho người đọc trong tương lai sử dụng các hàm 'Async': 'readdirAsync',' readFileAsync'. – Wtower