复杂的承诺和 for 循环
Complex promises and for loops
一段时间以来,我一直在为复杂的 for/promise 妆容而苦恼。我不能使用 async/await,因为 azure functions v1 不支持它。
问题如下...
我得到了一个数组allArray
现在我想完成类似下面的事情,但我似乎很难过。
编辑:
问题似乎是函数到达 loop
并通过 for 循环发送 allArray[0]
并且我得到 context.log("One: " + results[0], "Two: " + results[1]);
返回,但它不会在发送空 anotherArray
之前等待,它也不会启动 var call
也不会启动下一个循环。
我的日志如下所示:
no thanks (oneAnalysis)
No things (twoAnalysis)
Done again
[]
Done
One: " + results[0], "Two: " + results[1]
Function completed
如有任何帮助,我们将不胜感激。
module.exports = function (context, allArray) {
var loopPromise = loop(context, allArray);
Promise.all([loopPromise]).then(function(results){
context.log('Done again');
context.log(results[0]);
context.done()
});
}
function loop (context, allArray) {
var anotherArray = [];
for (i = 0; i < allArray.length; i++) {
var promiseOne = oneAnalysis (context, allArray[i]);
var promiseTwo = twoAnalysis (context, allArray[i]);
Promise.all([promiseOne, promiseTwo]).then(function(results){
context.log('Done');
context.log("One: " + results[0], "Two: " + results[1]);
var Id = allArray[i].Id;
var call = callCF (context, Id)
anotherArray.push(call);
});
}
return Promise.all(anotherArray);
}
function oneAnalysis (context, input) {
if (input.something.length > 0) {
var somethingArray = [];
for (i = 0; i < input.something.length; i++) {
if (stuff) {
var queue = queue;
var text = {
text
}
var create = createMessage(text, queue, context);
somethingArray.push(create);
} else {
somethingArray.push("no thanks");
}
}
return Promise.all(somethingArray);
} else {
return ("No things");
}
}
function twoAnalysis (context, input) {
same as oneAnalysis
}
function createMessage(text, queue, context) {
return new Promise((resolve, reject) => {
queueService.createMessage(queue, JSON.stringify(text), function(error) {
if (!error) {
context.log('Message inserted:', text);
resolve ('Message inserted: ' + text)
}
else {
context.log('All done');
resolve ('error');
}
});
});
}
function callCF(context, id) {
return new Promise((resolve, reject) => {
Do http request and resolve on end
});
}
你的 loop
方法在我看来有问题,你没有等待循环中生成的承诺在对 anotherArray
采取行动之前解决,这可能是你看到奇怪行为的原因。
您应该重组该方法,以便在尝试解析 anotherArray
.
之前正确解析旨在影响 anotherArray
的承诺
function loop (context, allArray) {
var anotherArray = [];
var processing = allArray.map(function(elem) {
var promiseOne = oneAnalysis(context, elem);
var promiseTwo = twoAnalysis(context, elem);
return Promise.all([promiseOne, promiseTwo]).then(function(results){
context.log('Done');
context.log("One: " + results[0], "Two: " + results[1]);
var Id = elem.Id;
var call = callCF(context, Id)
anotherArray.push(call);
});
});
return Promise.all(processing).then(function() {
return Promise.all(anotherArray);
});
}
async
/await
很好,但最终它们只是常规承诺之上的糖分。正如我在对您的问题的评论中提到的,我正在根据我的理解对您的伪代码和重构代码做出一些假设。
既然你可以使用promises,我想你也可以使用const和箭头函数;如果不是这种情况,请告诉我,我可以重构我的代码。
module.exports = (context, allArray) => {
// loop returns a promise already from Promise.all so we do not need to wrap
// it in another promise.
loop(context, allArray).then(results => {
context.log('Done again');
context.log(results[0]);
context.done()
});
}
function loop(context, allArray) {
// this reduce will take every item in `allArray`
const anotherArray = allArray.reduce((accumulator, item) => {
// For each item in anotherArray, call oneAnalysis and twoAnalysis; return
// values are promises and we need to wait for them to resolve using
// Promise.all.
const promiseOne = oneAnalysis(context, item);
const promiseTwo = twoAnalysis(context, item);
const callCFPromise = Promise.all([promiseOne, promiseTwo]).then(results => {
context.log('Done');
context.log('One: ' + results[0], 'Two: ' + results[1]);
const Id = allArray[i].Id;
// Once promiseOne and promiseTwo are resolved call callCF which returns
// another promise itself. This is the final promised to be returned to
// callCFPromise.
return callCF(context, Id);
});
// callCFPromise will be a promise to be resolved with the value of callCF
// after promiseOne and promiseTwo are resolved. We are inside a reduce so
// we need to push our promise in the accumulator and return it for the next
// iteration.
accumulator.push(callCFPromise);
return accumulator;
}, []);
return Promise.all(anotherArray);
}
function oneAnalysis(context, input) {
if (!input.something.length) {
return 'No things';
}
// Take every item in `input.something`, and if `stuff` is truthy, it will
// call createMessage, and push the promise to accumulator. in the end, the
// resulting accumulator (array of promises) will be returned. In the original
// version of this code I did not see any reference input.something[i] so in
// this case I am not doing anything to item, but I guess it will be used for
// something.
const createPromises = input.something.reduce((accumulator, item) => {
if (!stuff) {
photoArray.push('no thanks');
} else {
// I am guessing these queue and text have something to do with item (which
// is input.something[i] in the original shared code)
const queue = queue;
const text = { text };
const create = createMessage(text, queue, context);
// Since we are in a reduce, we need to push our create promise into the
// accumulator and return it for the next iteration. In this case we only
// push the promises we create instead of every iteration.
accumulator.push(create);
}
return accumulator;
}, []);
// Take the resulting accumulator of promises and create a new promise that
// resolves when every promise in the array is resolved.
return Promise.all(createPromises);
}
function twoAnalysis(context, input) {
// same as oneAnalysis
}
function createMessage(text, queue, context) {
return new Promise((resolve, reject) => {
queueService.createMessage(queue, JSON.stringify(text), error => {
if (error) {
return reject(error);
}
context.log('Message inserted:', text);
return resolve('Message inserted: ' + text);
});
});
}
function callCF(context, id) {
return new Promise((resolve, reject) => {
// Do http request and resolve on end
});
}
一段时间以来,我一直在为复杂的 for/promise 妆容而苦恼。我不能使用 async/await,因为 azure functions v1 不支持它。
问题如下...
我得到了一个数组allArray
现在我想完成类似下面的事情,但我似乎很难过。
编辑:
问题似乎是函数到达 loop
并通过 for 循环发送 allArray[0]
并且我得到 context.log("One: " + results[0], "Two: " + results[1]);
返回,但它不会在发送空 anotherArray
之前等待,它也不会启动 var call
也不会启动下一个循环。
我的日志如下所示:
no thanks (oneAnalysis)
No things (twoAnalysis)
Done again
[]
Done
One: " + results[0], "Two: " + results[1]
Function completed
如有任何帮助,我们将不胜感激。
module.exports = function (context, allArray) {
var loopPromise = loop(context, allArray);
Promise.all([loopPromise]).then(function(results){
context.log('Done again');
context.log(results[0]);
context.done()
});
}
function loop (context, allArray) {
var anotherArray = [];
for (i = 0; i < allArray.length; i++) {
var promiseOne = oneAnalysis (context, allArray[i]);
var promiseTwo = twoAnalysis (context, allArray[i]);
Promise.all([promiseOne, promiseTwo]).then(function(results){
context.log('Done');
context.log("One: " + results[0], "Two: " + results[1]);
var Id = allArray[i].Id;
var call = callCF (context, Id)
anotherArray.push(call);
});
}
return Promise.all(anotherArray);
}
function oneAnalysis (context, input) {
if (input.something.length > 0) {
var somethingArray = [];
for (i = 0; i < input.something.length; i++) {
if (stuff) {
var queue = queue;
var text = {
text
}
var create = createMessage(text, queue, context);
somethingArray.push(create);
} else {
somethingArray.push("no thanks");
}
}
return Promise.all(somethingArray);
} else {
return ("No things");
}
}
function twoAnalysis (context, input) {
same as oneAnalysis
}
function createMessage(text, queue, context) {
return new Promise((resolve, reject) => {
queueService.createMessage(queue, JSON.stringify(text), function(error) {
if (!error) {
context.log('Message inserted:', text);
resolve ('Message inserted: ' + text)
}
else {
context.log('All done');
resolve ('error');
}
});
});
}
function callCF(context, id) {
return new Promise((resolve, reject) => {
Do http request and resolve on end
});
}
你的 loop
方法在我看来有问题,你没有等待循环中生成的承诺在对 anotherArray
采取行动之前解决,这可能是你看到奇怪行为的原因。
您应该重组该方法,以便在尝试解析 anotherArray
.
anotherArray
的承诺
function loop (context, allArray) {
var anotherArray = [];
var processing = allArray.map(function(elem) {
var promiseOne = oneAnalysis(context, elem);
var promiseTwo = twoAnalysis(context, elem);
return Promise.all([promiseOne, promiseTwo]).then(function(results){
context.log('Done');
context.log("One: " + results[0], "Two: " + results[1]);
var Id = elem.Id;
var call = callCF(context, Id)
anotherArray.push(call);
});
});
return Promise.all(processing).then(function() {
return Promise.all(anotherArray);
});
}
async
/await
很好,但最终它们只是常规承诺之上的糖分。正如我在对您的问题的评论中提到的,我正在根据我的理解对您的伪代码和重构代码做出一些假设。
既然你可以使用promises,我想你也可以使用const和箭头函数;如果不是这种情况,请告诉我,我可以重构我的代码。
module.exports = (context, allArray) => {
// loop returns a promise already from Promise.all so we do not need to wrap
// it in another promise.
loop(context, allArray).then(results => {
context.log('Done again');
context.log(results[0]);
context.done()
});
}
function loop(context, allArray) {
// this reduce will take every item in `allArray`
const anotherArray = allArray.reduce((accumulator, item) => {
// For each item in anotherArray, call oneAnalysis and twoAnalysis; return
// values are promises and we need to wait for them to resolve using
// Promise.all.
const promiseOne = oneAnalysis(context, item);
const promiseTwo = twoAnalysis(context, item);
const callCFPromise = Promise.all([promiseOne, promiseTwo]).then(results => {
context.log('Done');
context.log('One: ' + results[0], 'Two: ' + results[1]);
const Id = allArray[i].Id;
// Once promiseOne and promiseTwo are resolved call callCF which returns
// another promise itself. This is the final promised to be returned to
// callCFPromise.
return callCF(context, Id);
});
// callCFPromise will be a promise to be resolved with the value of callCF
// after promiseOne and promiseTwo are resolved. We are inside a reduce so
// we need to push our promise in the accumulator and return it for the next
// iteration.
accumulator.push(callCFPromise);
return accumulator;
}, []);
return Promise.all(anotherArray);
}
function oneAnalysis(context, input) {
if (!input.something.length) {
return 'No things';
}
// Take every item in `input.something`, and if `stuff` is truthy, it will
// call createMessage, and push the promise to accumulator. in the end, the
// resulting accumulator (array of promises) will be returned. In the original
// version of this code I did not see any reference input.something[i] so in
// this case I am not doing anything to item, but I guess it will be used for
// something.
const createPromises = input.something.reduce((accumulator, item) => {
if (!stuff) {
photoArray.push('no thanks');
} else {
// I am guessing these queue and text have something to do with item (which
// is input.something[i] in the original shared code)
const queue = queue;
const text = { text };
const create = createMessage(text, queue, context);
// Since we are in a reduce, we need to push our create promise into the
// accumulator and return it for the next iteration. In this case we only
// push the promises we create instead of every iteration.
accumulator.push(create);
}
return accumulator;
}, []);
// Take the resulting accumulator of promises and create a new promise that
// resolves when every promise in the array is resolved.
return Promise.all(createPromises);
}
function twoAnalysis(context, input) {
// same as oneAnalysis
}
function createMessage(text, queue, context) {
return new Promise((resolve, reject) => {
queueService.createMessage(queue, JSON.stringify(text), error => {
if (error) {
return reject(error);
}
context.log('Message inserted:', text);
return resolve('Message inserted: ' + text);
});
});
}
function callCF(context, id) {
return new Promise((resolve, reject) => {
// Do http request and resolve on end
});
}