#javascript #node.js #angular #promise #angular-promise
#javascript #node.js #angular #обещание #angular-обещание
Вопрос:
Я выполняю вызов API, используя Promise.all
, как показано ниже:
Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
return this.serviceC.status(hostName)
.then(res => {
return new Promise((resolve, reject) => {
const oretry: ORInterface = {
oQid: res.rows[0].qid,
reason: this.reason
};
this.serviceB.retry(oretry).subscribe(resolve);
});
});
}))
.then(() => {
this.dialog.close();
})
.catch(err => {
console.log(err);
});
Приведенный выше код работает нормально.
Теперь я хочу выполнить еще один вызов API после успешного завершения this.serviceB.retry(oretry)
.
Второй API является this.serviceB.createDbEntry(sentry)
и sentry
выглядит следующим образом:
const sretry: SDInterface = {
hostName,
Id: this.Id.slice(0, this.Id.length),
reason: this.reason
};
И я делаю это, как показано ниже
Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
return this.serviceC.status(hostName)
.then(res => {
return new Promise((resolve, reject) => {
const oretry: ORInterface = {
oQid: res.rows[0].qid,
reason: this.reason
};
const sretry: SDInterface = {
hostName,
Id: this.Id.slice(0, this.Id.length),
reason: this.reason
};
this.serviceB.retry(oretry).subscribe(resolve);
this.serviceB.createDbEntry(sentry).subscribe(resolve);
});
});
}))
.then(() => {
this.dialog.close();
})
.catch(err => {
console.log(err);
});
Приведенный выше код выдает ошибку:
error: "SequelizeValidationError: string violation: Id cannot be an array or an object"
Похоже, что он не вызывает второй API для каждого Id
Ответ №1:
Возможно, вы захотите взглянуть на forkJoin
import { Observable, forkJoin } from 'rxjs';
И затем
ngOnInit() {
let one = this.http.get('some/api/1') //some observable;
let two = this.http.get('some/api/2') // another observable;
forkJoin([one, tow]).subscribe(response => {
// results[0] is our one call
// results[1] is our second call
let var1 = response[1];
let var2 = response[0];
}/*, error => { in case error handler } */);
}
Ответ №2:
Не лучше ли было бы использовать Promise.all()
еще раз?
Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
return this.serviceC.status(hostName)
.then(res => {
return new Promise((resolve, reject) => {
const oretry: ORInterface = {
oQid: res.rows[0].qid,
reason: this.reason
};
this.serviceB.retry(oretry).subscribe(resolve);
});
})
.then(() => {
return Promise.all(this.Id.slice(0, this.Id.length).map(id => {
return new Promise((resolve, reject) => {
const sretry: SDInterface = {
hostName,
Id: id,
reason: this.reason
};
this.serviceB.createDbEntry(sentry).subscribe(resolve);
});
})
});
}))
.then(() => {
this.dialog.close();
})
.catch(err => {
console.log(err);
});
И использование toPromise()
сделает код более кратким.
Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
return this.serviceC.status(hostName)
.then(res => {
const oretry: ORInterface = {
oQid: res.rows[0].qid,
reason: this.reason
};
return this.serviceB.retry(oretry).toPromise();
})
.then(() => {
return Promise.all(this.Id.slice(0, this.Id.length).map(id => {
const sretry: SDInterface = {
hostName,
Id: id,
reason: this.reason
};
this.serviceB.createDbEntry(sentry).toPromise();
})
});
}))
.then(() => {
this.dialog.close();
})
.catch(err => {
console.log(err);
});
Комментарии:
1. Я пытаюсь использовать
toPromise()
, но получаю ошибкуTSLint: Missing semicolon(semicolon)
2. Ошибка с запятой устранена путем добавления еще одной скобки,
...this.serviceB.createDbEntry(sentry).toPromise(); })); });
пожалуйста, обратите внимание, что теперьthis.serviceB.createDbEntry(sentry).toPromise();
выполняется два раза вместо одного. Можете ли вы, пожалуйста, проверить?
Ответ №3:
Используйте combineLatest, в Angular мы используем RxJS, а не promises.
combineLatest(
[this.http.get('call1'), this.http.get('call2')]
).subscribe(([result1, result2]) => {
// do stuff with result1 and result2
});
Комментарии:
1. У меня есть зависимость от
promise
. Я могу заставить это работать, используяtoPromise()
приведенный выше ответ. Единственное, чтоthis.serviceB.createDbEntry(sentry).toPromise();
выполняется дважды вместо одного раза. Можете ли вы, пожалуйста, проверить?
Ответ №4:
promise.all
принимает входные данные в массив и выдает ответ в массиве,
Создайте 2 функции, каждая из которых с вашей асинхронной логикой возвращает обещание,
Скажите funcA и funcB, затем используйте ниже, чтобы вызвать их параллельно
Promise.all([funcA(this.hostName), funcB(this.id)])
.then(respones => {
console.log(responses[0]); //return value for funcA
console.log(responses[1]); //return value for funcB
})
.catch(err => console.log(err));
Я предполагаю, что ваша логика функций верна, я просто скопировал ваш вопрос и дал им структуру
const funcA = (hostName) => {
hostName.slice(0, this.Id.length).map((hostName) => {
return this.serviceC.status(hostName)
.then(res => {
return new Promise((resolve, reject) => {
const oretry: ORInterface = {
oQid: res.rows[0].qid,
reason: this.reason
};
this.serviceB.retry(oretry).subscribe(resolve);
});
});
});
}
const funcB = (Id) => {
Id.slice(0, this.Id.length).map(id => {
return new Promise((resolve, reject) => {
const sretry: SDInterface = {
hostName,
Id: id,
reason: this.reason
};
this.serviceB.createDbEntry(sentry).subscribe(resolve);
});
})
}
Комментарии:
1. Не могли бы вы обновить свой ответ и показать, как использовать
this.hostName.slice(0, this.Id.length)
вfuncA
и использоватьthis.Id.slice(0, this.Id.length)
вfuncB
?2.
funcB
выдает ошибкуTS2663: Cannot find name 'hostName'. Did you mean the instance member 'this.hostName'?
3. Как передать
hostName
изfuncA
вfuncB
?4.
funcB
все еще выдает ошибкуTS2304: Cannot find name 'hostName