2012-08-11 15 views
7

Làm cách nào để quản lý lưu hàng loạt trong Mongoose? Tôi thấy nó có thể không thể nào được nêu:Mongoose JS hứa hẹn? Hoặc cách quản lý hàng loạt lưu

Theres một số đề cập về việc sử dụng một số thư viện kiểm soát dòng chảy như q, nhưng tôi cũng nhận thấy có promises trong mongoose, nó có thể được sử dụng? Tôi có thể làm như thế nào trong jQuery Hoãn/Promises

$.when(obj1.save(), obj2.save(), obj3.save()).then -> 
    # do something? 

Trả lời

3

Thử chức năng parallel của mô-đun async.

var functions = []; 

for (var i=0; i < docs.length; i++) { 
    functions.push((function(doc) { 
     return function(callback) { 
      doc.save(callback); 
     }; 
    })(docs[i])); 
} 

async.parallel(functions, function(err, results) { 
    console.log(err); 
    console.log(results); 
}); 
2

Để lưu nhiều tài liệu mongoose song song, bạn có thể làm một cái gì đó đơn giản như thế này (giả sử bạn có một mảng tên docs các văn bản để lưu):

var count = docs.length; 
docs.forEach(function(doc) { 
    doc.save(function(err, result) { 
     if (--count === 0) { 
      // All done; call containing function's callback 
      return callback(); 
     } 
    }); 
}); 
1

Một ví dụ tinh tế về cách sử dụng async parallel sẽ là:

async.parallel([obj1.save, obj2.save, obj3.save], callback); 

Kể từ khi Công ước là như nhau trong Mongoose như trong async (err, callback), bạn không cần phải bọc chúng trong callbacks của riêng bạn, chỉ cần thêm các cuộc gọi của bạn lưu trong một mảng và bạn sẽ nhận được một cuộc gọi lại khi tất cả được hoàn tất.

+1

Hoặc để lô-lưu một mảng: async.map (đối tượng, hàm (đối tượng, tiếp theo) {object.save (tiếp theo)}, gọi lại); –

+0

Cảm ơn. Tôi nghĩ phương pháp tiếp cận bản đồ tốt hơn. Nhưng cả hai đều ổn. –

9

Có, bạn có thể thực hiện điều này với lời hứa. mã nếu bạn đang sử dụng thư viện Q lời hứa, bạn có thể re-write @ matz3 của như:

var tasks = []; 

for (var i=0; i < docs.length; i++) { 
    tasks.push(docs[i].save()); 
} 

Q.all(tasks) 
    .then(function(results) { 
    console.log(results); 
    }, function (err) { 
    console.log(err); 
    }); 

Chúng tôi bắt đầu tất cả các hoạt động cùng một lúc trong vòng lặp, nhưng chúng tôi không chờ đợi bất kỳ người trong số họ hoàn chỉnh, vì vậy chúng chạy song song. Chúng tôi thêm một lời hứa (hoạt động như một trình giữ chỗ cho kết quả) vào một mảng. Sau đó, chúng tôi chờ đợi tất cả các lời hứa trong mảng hứa hẹn sẽ hoàn thành.

tốt Hầu hết Promises/A+ thư viện tương thích có một số tương đương với Q.all

+0

Tính năng mới này có thể sai. Nhưng lưu của bạn() có khi xây dựng mảng, bạn không nên loại trừ() để nó không đánh giá trong khi xây dựng mảng? – Slappy

+1

Không, tôi bắt đầu các hoạt động trong mảng, vì vậy tôi cần phải bao gồm '()'. Sau đó, trả về một đối tượng 'lời hứa' mà tôi đặt vào mảng. Nó là song song bởi vì tôi chỉ nhận được một lời hứa, không phải là kết quả cuối cùng thực tế. Cuối cùng, tôi đợi những lời hứa đó để giải quyết. – ForbesLindesay

+1

Nếu tôi bỏ qua '()', tôi sẽ nhận được một mảng các hàm, và không có điều được thừa nhận phổ biến nào để làm với một mảng các hàm. Ví dụ, tôi có thể muốn họ thực hiện một lần tại một thời điểm thay vì song song, hoặc họ có thể gọi lại thay vì trả lời một lời hứa. Tuy nhiên, có một cách được công nhận để chờ đợi một loạt các lời hứa được hoàn thành. – ForbesLindesay

-1

gì về async.queue.
Một ví dụ đơn giản:

var queue = async.queue(function(obj, callback) { 
    return obj.save(callback); 
}); 

for (var i in objs) { 
    var obj = objs[i]; 
    // Some changes on object obj 
    queue.push(obj); 
} 

Nếu bạn cần một gọi lại sau khi hàng đợi được làm trống:

var emptyQueue = true; 
var queue = async.queue(function(obj, callback) { 
    return obj.save(callback); 
}); 
queue.drain = function() { 
    // Every callbacks are finished 
    // bigCallback(); 
}; 

for (var i in objs) { 
    var obj = objs[i]; 
    // Some changes on object obj 
    queue.push(obj); 
    emptyQueue = false; 
} 
if (emptyQueue) { 
    // Call manually queue drain in case of the queue is empty 
    // and we need to call bigCallback() for example 
    return queue.drain(); 
} 
+0

Tại sao một downvote? – mathieug

-1

@ForbesLindesay Tại sao tải một thư viện bên ngoài khi bạn có thể sử dụng thực hiện mongoose những lời hứa và tạo riêng của bạn Tất cả các ?

Tạo mô-đun tăng cường lời hứa với tất cả.

var Promise = require("mongoose").Promise; 

Promise.all = function(promises) { 
    var mainPromise = new Promise(); 
    if (promises.lenght == 0) { 
    mainPromise.resolve(null, promises); 
    } 

    var pending = 0; 
    promises.forEach(function(p, i) { 
    pending++; 
    p.then(function(val) { 
     promises[i] = val; 
     if (--pending === 0) { 
     mainPromise.resolve(null, promises); 
     } 
    }, function(err) { 
     mainPromise.reject(err); 
    }); 
    }); 

    return mainPromise; 
} 

module.exports = Promise; 

Sau đó, sử dụng nó với cầy mangut:

require('./promise') 

... 

var tasks = []; 

for (var i=0; i < docs.length; i++) { 
    tasks.push(docs[i].save()); 
} 

mongoose.Promise.all(tasks) 
    .then(function(results) { 
    console.log(results); 
    }, function (err) { 
    console.log(err); 
    }); 
+0

Vâng, có vẻ đơn giản hơn khi sử dụng mpromise được sử dụng bên trong mongoose: 'var Promise = require ('mpromise');' sau đó sử dụng 'Promise.all (...)'. –

4

mongoose bây giờ cho phép bạn chọn những hứa thực hiện.

Ở đây tôi đang sử dụng nút.hệ thống js mặc định Promise (ES6) nướng vào nodejs

var mongoose = require('mongoose'); 
    mongoose.Promise = global.Promise; // use system implementation 

Promise.all(obj1.save(), obj2.save(), obj3.save()) 
.then(function(resultSaves) { 

    console.log('parallel promise save result :'); 
    console.log(resultSaves); 
    mongoose.disconnect(); 

}).catch(function(err) { 

    console.log('ERROR on promise save :'); 
    console.log(err); 
    mongoose.disconnect(); 
}); 

nút --version v4.1.1

[email protected]

1

Kể từ mongoose bây giờ hỗ trợ hứa hẹn bạn có thể sử dụng Promise.all().then(), vì vậy nó sẽ trở lại khi tất cả các lời hứa được giải quyết.

Promise.all([ 
    obj1.save(), 
    obj2.save(), 
    obj3.save() 
]) 
.then(console.log) 
.catch(console.error) 

Trong thực tế, nếu bạn luôn gọi phương thức save() bạn có thể sử dụng Array.map() đây:

Promise.all([ obj1, obj2, obj3 ].map(obj => obj.save()) 

Aaand cũng sử dụng cú pháp es6 để destructure mảng kết quả:

Promise.all([ obj1, obj2, obj3 ].map(obj => obj.save()) 
.then(([ savedObj1, savedObj2, savedObj3 ]) => { 
    // do something with your saved objects... 
})