我使用mbostock/queue对一些异步操作进行排队。这更多的是为了限制速率(UI生成的事件很少,后端可以缓慢处理),也要确保它们按顺序处理。我像一样使用它
function request(d, cb) {
//some async oper
add.then(function(){
cb(null, "finished ")
})
}
var addQ = queue(1);
addQ.defer(request) //called by few req at higher rates generated by UI
我已经使用angular.js$q进行异步操作了。那么,我必须使用mbostock/queue
吗,或者我可以从$q
构建一个队列吗(这在精神上是这样的https://github.com/kriskowal/q)
谢谢。
基本$q链示例
是的,可以使用Angular的$q!下面的示例向您展示了如何使用递归创建任意长度的队列。每个帖子都是连续出现的(一个接一个)。直到第一个帖子结束,第二个帖子才会开始。
这在写入数据库时非常有用。如果数据库在后端没有自己的队列,并且您同时进行多次写入,您可能会发现并非所有数据都已保存!
我添加了一个Plunkr示例来演示此代码的实际操作。
$scope.setData = function (data) {
// This array will hold the n-length queue
var promiseStack = [];
// Create a new promise (don't fire it yet)
function newPromise (key, data) {
return function () {
var deferred = $q.defer();
var postData = {};
postData[key] = data;
// Post the the data ($http returns a promise)
$http.post($scope.postPath, postData)
.then(function (response) {
// When the $http promise resolves, we also
// resolve the queued promise that contains it
deferred.resolve(response);
}, function (reason) {
deferred.reject(reason);
});
return deferred.promise;
};
}
// Loop through data creating our queue of promises
for (var key in data) {
promiseStack.push(newPromise(key, data[key]));
}
// Fire the first promise in the queue
var fire = function () {
// If the queue has remaining items...
return promiseStack.length &&
// Remove the first promise from the array
// and execute it
promiseStack.shift()()
// When that promise resolves, fire the next
// promise in our queue
.then(function () {
return fire();
});
};
// Begin the queue
return fire();
};
您可以使用一个简单的函数来开始您的队列。为了进行此演示,我将一个充满密钥的对象传递给一个函数,该函数将把这些密钥拆分为单独的帖子,然后将它们POST到Henry的HTTPPost-DumpingServer。(谢谢亨利!)
$scope.beginQueue = function () {
$scope.setData({
a: 0,
b: 1,
/* ... all the other letters of the alphabet ... */
y: 24,
z: 25
}).then(function () {
console.log('Everything was saved!');
}).catch(function (reason) {
console.warn(reason);
});
};
如果您想试用此代码,这里有一个指向Plunkr示例的链接。
简单的答案是否定的,您不需要额外的库。Promise.then()足够"原子"。详细的答案是:值得制作一个queue()函数来保持代码干燥。Bluebird的承诺似乎相当完整,但这里有一些基于AngularJS的$q的内容。
如果我正在制作.requeue(),我希望它也能处理错误。
这是一个角度服务工厂,以及一些用例:
/**
* Simple promise factory
*/
angular.module('app').factory('P', function($q) {
var P = $q;
// Make a promise
P.then = function(obj) {
return $q.when(obj);
};
// Take a promise. Queue 'action'. On 'action' faulure, run 'error' and continue.
P.queue = function(promise, action, error) {
return promise.then(action).catch(error);
};
// Oook! Monkey patch .queue() onto a $q promise.
P.startQueue = function(obj) {
var promise = $q.when(obj);
promise.queue = function(action, error) {
return promise.then(action).catch(error);
};
return promise;
};
return P;
});
如何使用:
.run(function($state, YouReallyNeedJustQorP, $q, P) {
// Use a $q promise. Queue actions with P
// Make a regular old promise
var myPromise = $q.when('plain old promise');
// use P to queue an action on myPromise
P.queue(myPromise, function() { return console.log('myPromise: do something clever'); });
// use P to queue an action
P.queue(myPromise, function() {
throw console.log('myPromise: do something dangerous');
}, function() {
return console.log('myPromise: risks must be taken!');
});
// use P to queue an action
P.queue(myPromise, function() { return console.log('myPromise: never quit'); });
// Same thing, but make a special promise with P
var myQueue = P.startQueue(myPromise);
// use P to queue an action
myQueue.queue(function() { return console.log('myQueue: do something clever'); });
// use P to queue an action
myQueue.queue(function() {
throw console.log('myQueue: do something hard');
}, function() {
return console.log('myQueue: hard is interesting!');
});
// use P to queue an action
myQueue.queue(function() { return console.log('myQueue: no easy days'); });
链式承诺
Angular的$q
实现允许您链接承诺,然后根据自己的逻辑处理这些承诺的解析。方法与mbostock/queue
有点不同,但意图相同。创建一个函数来确定如何解决您的延迟问题(创建承诺),然后将这些功能提供给更高级别的控制器/服务以进行特定的解决处理。
Angular使用$q.defer()
返回promise对象,然后可以在应用程序逻辑中按您希望的顺序调用这些对象。(甚至跳过、变异、拦截等)
我会写一些代码,但我在egghead.io上发现这段7分钟的视频是最好的短演示:https://egghead.io/lessons/angularjs-chained-promises,而且它在解释方面会做得更好。Thomas(演讲者)构建了一个非常小的飞行仪表板应用程序,用于排队查看天气和航班数据,并在用户查询其信息时处理该队列。ThomasBurleson/angularjs-FlightDashboard
我将在codepen上设置一个较小的演示,使用"在餐厅吃饭"的情况来演示这个概念:http://codepen.io/LongLiveCHIEF/pen/uLyHx
此处的代码示例:
https://gist.github.com/LongLiveCHIEF/4c5432d1c2fb2fdf937d