javascript 排队承诺
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21799269/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Queuing promises
提问by bsr
I use mbostock/queuefor queuing few async operation. It is more to rate limit (UI generate few events, where the backend can process it slowly), and also to make sure they are processed sequentially. I use it like
我使用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
I already uses angular.js $q for async operation. So, do I have to use mbostock/queue
, or can I build a queue out of $q
(which is in spirit https://github.com/kriskowal/q)
我已经使用 angular.js $q 进行异步操作。那么,我是否必须使用mbostock/queue
,或者我可以建立一个队列$q
(本质上是https://github.com/kriskowal/q)
Thanks.
谢谢。
采纳答案by f1lt3r
Basic $q Chain Example
基本的 $q 链示例
Yes you canbuild a chained queue using Angular's $q! Here is an example that shows you how you could use recursion to create a queue of any length. Each post happens in succession (one after another). The second post will not start until the first post has finished.
是的,您可以使用 Angular 的 $q 构建一个链式队列!这是一个示例,向您展示了如何使用递归来创建任意长度的队列。每个帖子相继发生(一个接一个)。在第一篇文章完成之前,不会开始第二篇文章。
This can be helpful when writing to databases. If the database does not have it's own queue on the backend, and you make multiple writes at the same time, you may find that not all of your data is saved!
这在写入数据库时会很有帮助。如果数据库在后端没有自己的队列,并且您同时进行多次写入,您可能会发现并非所有数据都被保存!
I have added a Plunkr exampleto demonstrate this code in action.
我添加了一个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();
};
You can use a simple function to begin your queue. For the sake of this demonstration, I am passing an object full of keys to a function that will split these keys into individual posts, then POST them to Henry's HTTP Post Dumping Server. (Thanks Henry!)
您可以使用一个简单的函数来开始您的队列。为了这个演示,我将一个充满键的对象传递给一个函数,该函数将这些键拆分为单独的帖子,然后将它们发布到Henry 的 HTTP Post Dumping Server。(感谢亨利!)
$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);
});
};
Here is a link to the Plunkr exampleif you would like to try out this code.
如果您想尝试此代码,请访问Plunkr 示例的链接。
回答by Michael Cole
The short answer is no, you don't need an extra library. Promise.then() is sufficiently "atomic". The long answer is: it's worth making a queue() function to keep code DRY. Bluebird-promisesseems pretty complete, but here's something based on AngularJS's $q.
简短的回答是否定的,您不需要额外的库。Promise.then() 足够“原子”。长答案是:值得创建一个 queue() 函数来保持代码干燥。 Bluebird-promises看起来很完整,但这里有一些基于 AngularJS 的 $q。
If I was making .queue() I'd want it to handle errors as well.
如果我正在制作 .queue() 我希望它也能处理错误。
Here's an angular service factory, and some use cases:
这是一个角度服务工厂,以及一些用例:
/**
* 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;
});
How to use it:
如何使用它:
.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'); });
回答by Brian Vanderbusch
Chained Promises
连锁承诺
Angular's $q
implementation allows you to chain promises, and then handle resolves of those promises according to your own logic. The methods are a bit different than mbostock/queue
, but the intent is the same. Create a function that determines how your defered will be resolved (creating a promise), then make these available to a higher level controller/service for specific resolution handling.
Angular 的$q
实现允许您链接承诺,然后根据您自己的逻辑处理这些承诺的解析。方法与 略有不同mbostock/queue
,但意图相同。创建一个函数来确定如何解决您的延迟(创建承诺),然后将它们提供给更高级别的控制器/服务以进行特定的解析处理。
Angular uses $q.defer()
to return promise objects, which can then be called in the order you wish inside your application logic. (or even skipped, mutated, intercepted, etc...).
Angular 用于$q.defer()
返回 promise 对象,然后可以在应用程序逻辑中按照您希望的顺序调用这些对象。(甚至跳过,变异,拦截等......)。
I'll throw down some code, but I found this 7 minute video at egghead.io to be the best short demo: https://egghead.io/lessons/angularjs-chained-promises, and it will do a FAR better job of explaining. Thomas (the presenter) builds a very small flight dashboard app that queues up weather and flight data, and processes that queue when a user queries their itenerary. ThomasBurleson/angularjs-FlightDashboard
我会丢掉一些代码,但我发现 egghead.io 上的这个 7 分钟视频是最好的简短演示:https://egghead.io/lessons/angularjs-chained-promises ,它会做得更好的解释。Thomas(演示者)构建了一个非常小的飞行仪表板应用程序,用于对天气和飞行数据进行排队,并在用户查询其行程时处理该队列。ThomasBurleson/angularjs-FlightDashboard
I will be setting up a smaller demonstration on codepen, using the situation of 'eating at a restaurant' to demonstrate this concept: http://codepen.io/LongLiveCHIEF/pen/uLyHx
我将在 codepen 上设置一个较小的演示,使用“在餐厅吃饭”的情况来演示这个概念:http: //codepen.io/LongLiveCHIEF/pen/uLyHx
Code examples here:
代码示例在这里: