मुझे ऐसे फ़ंक्शन में कुछ परेशानी हो रही है जो लूप समाप्त होने से AJAX कॉल से पहले वापस आती है। मैं कई अजाक्स कॉल करता हूं जिसका मुझे परिणाम मिलता है और मेरी तत्कालीन श्रृंखला पर उनका उपयोग करता है।
यहाँ मेरा कोड है
const delay = t => new Promise(resolve => setTimeout(resolve, t));
(async () => {
await delay(timeout);
let results: boolean[] = [];
for (let i = 0; i < times; i++) {
await this.ajaxService.postWithData("/api/v1/..",
arg,
(data) => {
results[i] = this.checkStep(data);
},
() => {
});
}
return results; // This returns before for loop containing ajaxServces calls ends
})().then((results) => {
// Do some things here using `results`
});
पोस्टविथडेटा
public request = (options: Options, successCallback: Function, errorCallback?: Function): void => {
var that = this;
$.ajax({
url: options.url,
type: options.method,
data: options.data,
cache: false,
success: function (d) {
successCallback(d);
},
error: function (d) {
if (errorCallback) {
errorCallback(d);
return;
}
}
});
}
मैंने SO उत्तरों की जाँच की है, उदा। https://stackoverflow.com/a/40329190/3264998
2 जवाब
आपका request
रैपर अच्छा नहीं है और दुर्भाग्य से हारून का ज्यादा बेहतर नहीं है। मैंने हाल के वर्षों में jQuery का अधिक उपयोग नहीं किया है, लेकिन मुझे लगता है कि इसमें अब वादा-आधारित एपीआई भी हैं। किसी भी तरह से आप कुछ सामान्य चाहते हैं जो मूल रूप से आपको $.ajax
का "वादा" संस्करण देता है ताकि आप await
के साथ काम कर सकें -
const defaultOpts =
{ method: 'GET', cache: false }
const request = (opts = {}) =>
new Promise
( (resolve, reject) =>
$.ajax({ ...defaultOpts, ...opts })
.done((req, status, res) => resolve(res))
.fail((req, status, err) => reject(err))
)
आपने न्यूनतम, पूर्ण, सत्यापन योग्य उदाहरण (एमवीसीई) प्रदान नहीं किया है, इसलिए यह आपकी सहायता करना कठिन बना देता है। हम times
या checkStep
के बारे में नहीं जानते हैं, इसलिए आपके इरादों के बारे में कुछ अनुमान लगाए गए थे। ऐसा कुछ आपके पहियों को फिर से चालू करने में मदद कर सकता है -
const main = async () =>
{ const steps =
[ request ("/api/v1/something..")
, request ("/api/v1/another..")
, request ("/api/v2/andthis..")
]
const res =
await Promise.all(steps)
console.log(res)
// [ <result1>, <result2>, <result3> ]
// I don't know what your checkStep does
// but something like this might work
res.forEach(r => this.checkStep(r))
// otherwise
// const checked =
// res.map(r => this.checkStep(r))
// ...
return res
}
main()
.then(res => console.log("all results", res))
// [ <result1>, <result2>, <result3> ]
.catch (e => ...)
यदि एक अनुरोध दूसरे पर निर्भर है, तो अनुरोधों को एक सरणी में रखना और फिर Promise.all
पर कॉल करना बहुत उपयुक्त नहीं है। नीचे दिए गए उदाहरण में हम किसी विशेष लेखक के लिए सभी पोस्ट को क्वेरी करते हैं। हम जिस काल्पनिक एपीआई से पूछताछ कर रहे हैं वह लेखक के username
के लिए पूछता है लेकिन हम केवल लेखक के id
को जानते हैं। इस मामले में, हम पहले लेखक के उपयोगकर्ता नाम को देखते हैं, फिर हम उपयोगकर्ता नाम द्वारा पोस्ट को क्वेरी कर सकते हैं -
const authorById = id =>
request({ url: '/authors', data: { id } })
const postsByAuthor = username =>
request ({ url: '/posts', data: { author: username } })
const main = () =>
{ const author =
await authorById (10)
// { id: 10, username: alice, email: alice@email.lol }
// this request depends on the result of the first request
const posts =
await postsByAuthor (author.username)
// [ { postId: 9, title: "hello world" }, { postId: 11, ... }, ... ]
// ...
}
कुछ इस तरह काम करना चाहिए
public request = (options: Options, successCallback: Function, errorCallback?: Function): Promise => {
return new Promise( (resolve, reject) => {
var that = this;
$.ajax({
url: options.url,
type: options.method,
data: options.data,
cache: false,
success: function (d) {
resolve(successCallback(d));
},
error: function (d) {
if (errorCallback) {
reject(errorCallback(d));
}
}
})};
}
साथ ही, आपने अपने फ़ंक्शन के लिए रिटर्न प्रकार निर्दिष्ट किया है, क्या आप टाइपस्क्रिप्ट का उपयोग करेंगे? सुनिश्चित नहीं है कि वादा वापसी प्रकार मान्य है। लेकिन विचार यह है कि आपको एक वादा वापस करने की जरूरत है।