在promise中,我需要在另一个promise之后或者在所述promise之后单独调用它们之后调用并处理不确定数量的异步API响应,但是在另一个之前调用并执行顺序。
var promiseA = function() {
return new Promise(function(resolve, reject) {
// 1. Establish objects needed from one API endpoint
// 2. Call API endpoint for each object and parse
// 3. Only then continue to next promise
}
}
var finalPromise = function() {
return new Promise(function(resolve, reject) {
//
}
}
promiseA()
.then(finalPromise)
所以在promiseA中,我发现我需要从API中单独轮询多少个对象。每个请求当然都是异步的。我需要进行这些调用并在调用最终promise之前处理响应。
我正在努力用promises确定这种模式,我可以动态地创建这些promise,并且只允许在执行和处理不确定和异步之后执行最终的promise。我曾与其他语言合作过,但我很难在Promise中看到它。
感谢任何帮助。
答案 0 :(得分:0)
我已经更改了以下评论的答案。既然,你提到了ES6的承诺,我会坚持这一点。我们可能会关注两种基本类型的回调。
从那以后,
1.DOM加载或其他一次性事件
var p = new Promise(function(res, rej) {
window.onload = res();
};
2.Plain回调:这些是不符合约定的回调。例如的setTimeout
var p = new Promise(function(res, rej){
setTimeout(function() {
//your business/view logic
success? res():rej(); //if successful resolve else reject
}, 2000);
});
在上述每种情况下,promise(var p)都可以被包装以由函数返回。
var myAsyncMethod = function () {
var p = new ... // as mentioned in 1 or 2
return p;
}
然后用法:
myAsyncMethod()
.then(function(){/* success-handler */})
.catch(function(/* failure-handler */));
根据您的问题,您可能有许多此类方法:
function baseAJAXCall (url) {
new Promise(functoin(rej, res) {
$.get(url, function(err, data){
if(err) {
rej();
}
else {
resolve(data);
}
});
}
};
function callAPIEndpoint(url) {
return baseAJAXCall(url);
}
function finalPromiseHandler () {
//your final business/view logic
}
//USAGE
callAPIEndpoint('/my-first-call')
.then(function(data){
var promiseArray = data.map(function(item){
return baseAJAXCall(item.url);
});
return Promise.all(promiseArray);
})
.then(finalPromiseHandler)
.catch(function(){
console.log('.error-message.');
});
参考:
以下评论的链接。
---老答:请过关---
我熟悉这个库:https://github.com/kriskowal/q。而且,您可以使用q.all
和q.allSettled
构造执行此操作。也许这就是你要找的东西。
通常,模式是创建一个返回promise的函数。
function someAsyncFuncName1(url) {
var def = q.defer();
//async function
$.get(url, function(err, data){ //suppose
if(err){
def.reject();
}
else {
def.resolve(data); //pass the data to the .then() handler.
}
});
return def.promise;
}
function someAsyncFuncName2() {
var def = q.defer();
//async function
setTimeout(function(){ //suppose
//do something
if(good) {
def.resolve();
} else {
def.reject();
}
}, 1000); //arbitrary timeout of 1 second
return def.promise;
}
用法:
q.all([someAsyncFuncName1('/api-1'), someAsyncFuncName2()])
.then(function() {
//final handler
});
在类似的思路上,如果你想等待所有的承诺返回,可以使用q.allSettled()
。
希望这会有所帮助。
--- EOF OLD ANSWER ---
答案 1 :(得分:0)
首先,如果PromiseA
中使用的异步函数不返回promise,则需要 promisify 它们。您可以使用Promise
构造函数执行此操作,但使用库(例如bluebird及其promisify
方法)会更好。
让我们想象一下,我们有两个函数getUserIdsAsync
和getUserAsync
。第一个on返回用户ID列表,getUserAsync
按userId
返回用户数据。而且你需要通过他们的ID获取用户列表。 PromiseA
的代码看起来如此:
var promiseA = function() {
return getUserIdsAsync()
.then(userIds => {
let ops = users.map(uid => getUserAsync(uid));
return Promise.all(ops);
});
}
答案 2 :(得分:0)
以下代码段显示的是不使用任何外部库(如bluebird)的解决方案。它遵循您问题中的代码片段(似乎比需要的更复杂)。
你必须收集数组中的所有api promisses。然后你可以致电Promise.all()
获得所有api promisses结束的承诺。然后你可以做一些最后的事情,比如解析每个承诺的结果,然后继续。
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var apiEndpoint = function (name) {
return new Promise( (resolve, reject) => {
setTimeout(() => resolve('API ' + name + ' job done'), 1000);
});
}
var promiseA = function() {
return new Promise( (resolve, reject) => {
const promisses = [];
for (var i=1; i < getRandomInt(3,6); i++) {
// 1. Establish objects needed from one API endpoint
promisses.push(apiEndpoint('This is number ' + i));
}
Promise.all(promisses).then( results => {
// do final stuff
for (const s of results) {
// 2. Call API endpoint for each object and parse
console.log(s);
}
// continue ...
// 3. Only then continue to next promise
resolve('now it is finished');
}).catch( err => reject(err) );
});
}
var finalPromise = function() {
return new Promise( (resolve, reject) => {
console.log('finalPromise');
resolve();
});
}
promiseA()
.then( () => finalPromise())
.catch(err => console.log(err) );
请注意,此解决方案不易阅读。使用外部库或减少promisses可以提高可读性。也许您应该看看async / await模式以获得更好(可读)的解决方案。
以下是使用async / await的解决方案:
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
const apiEndpoint = function (name) {
return new Promise( (resolve, reject) => {
setTimeout(() => resolve('API ' + name + ' job done'), 1000);
});
}
async function promiseParallel () {
const promisses = [];
for (let i = 1; i < getRandomInt(3,6); i++) {
promisses.push(apiEndpoint('This is number ' + i));
}
for (const p of promisses) {
const x = await p;
console.log(x);
}
return ('everything is done');
}
promiseParallel().then( result => {
console.log(result);
}).catch( err => console.log(err) );
如果您想按顺序调用promisses,可以替换为:
async function promiseSequ () {
for (let i = 1; i < getRandomInt(3,6); i++) {
const x = await apiEndpoint('This is number ' + i);
console.log(x);
}
return ('everything is done');
}