Function Does Not Wait Until the Data Is Downloaded

Function does not wait until the data is downloaded

The other answer is not a good replacement for the code you already had. A better way would be to continue using NSURLSession's data tasks to keep the download operation asynchronous and adding your own callback block to the method. You need to understand that the contents of the download task's block are not executed before you return from your method. Just look at where the call to resume() is for further evidence.

Instead, I recommend something like this:

func getImageFromServerById(imageId: String, completion: ((image: UIImage?) -> Void)) {
let url:String = "https://dummyUrl.com/\(imageId).jpg"

let task = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!) {(data, response, error) in
completion(image: UIImage(data: data))
}

task.resume()
}

Which can be called like this

getImageFromServerById("some string") { image in
dispatch_async(dispatch_get_main_queue()) {
// go to something on the main thread with the image like setting to UIImageView
}
}

How to make the function wait until response comes back

You can use the async/await pattern with Promises, something like this:

  zipFile = new JSZip();

async mapZip() {
try {
var response = await this.exportIcsReportInJSONFormat();
console.log("JSONFile", response)
this.jsonFile = response;
this.zipFile.file("ics-report_.json", response, { binary: true });
var content = await this.zipFile.generateAsync({ type: "blob" });
saveAs(content, "example.zip");
}
catch {
...
}

}

exportIcsReportInJSONFormat() {
this.icsService.getICSReport().toPromise();
}

Protractor test does not wait for file to be downloaded

await fs.existsSync(excelFile); is only waiting for the fs.existsSync function to complete (which returns true if the file does exist), not actually waiting for the file to exist.

You could try adding a browser.wait() which would wait the file to download like so.

await browser.wait(async function () {
return await fs.existsSync(excelFile);
}, 30*1000, "File has not downloaded within 30 seconds")

Pause a for loop until function is completed

None of your functions justifies the async keyword (if you're not using await, using async is nonsense).

But all of your functions are missing return. You need to return the promises you create in a function.

Compare - every code path ends in return:

// returns a promise for whatever downloadFile() produces
function getFile(version) {
return axios.request({ /* ... */ }).then((response) => {
return downloadFile(version, response.data.location);
}).catch(err => {
return {error: "Download failed", version, err};
});
}

// downloadFile() also returns a promise, so we return that
function downloadFile(version, data) {
if (version && data) {
const downloader = new Downloader({ /* ... */ });
return downloader.download();
}
throw new Error("Invalid arguments");
};


// `downloads` will be an array of promises, we can wait for them with `Promise.all()`
function main() {
const downloads = [];
for (let i = 7990; i < 7995; i++) {
downloads.push(getFile(i));
}
Promise.all(downloads).then((results) => {
// all downloads are done
}).catch(err => {
console.log(err);
});
}

You probably don't want to daisy-chain the downloads. You just want to wait until all are done. Promise.all() does that.

Swift: wait for app execution till file downloads ends

You have to make downloadFile really async by using the appropriate async URLSession API. The completion handler API doesn't wait.

func downloadFile (fileOnServer: String, fileOnDevice: URL) async throws {
guard let dataURL = URL(string: fileOnServer) else { throw URLError(.badURL) }
let (dataTempFileUrl, _) = try await URLSession.shared.download(from: dataURL)
try FileManager.default.moveItem(at: dataTempFileUrl, to: fileOnDevice)
}

In the task you have add a do - catch block to handle the error(s)

.task()
{
do {
print ("START downloadFile() ")
try await downloadFile(fileOnServer: htmlLinkForJSON, fileOnDevice: downloadedJSON)
try await downloadFile(fileOnServer: htmlLinkForCategories, fileOnDevice: downloadedCategories)
print ("END downloadFile()")
print ("---------")
print ("Start checkSavedFile()")
checkSavedFile(file: downloadedJSON)
checkSavedFile(file: downloadedCategories)
print ("END checkSavedFile()")
print ("---------")
} catch {
print(error)
}
}

Wait for async function and promises in it to finish

One option would be to have a loop that goes over the images and processes one after another. To then run multiple processings in parallel, start multiple loops:

  // Goes over the "data" array, calls and waits for each "task" and processes "runnerCount" tasks in parallel
function inParallel(task, data, runnerCount) {
let i = 0, results = [];

async function runner() {
while(i < data.length) {
const pos = i++; // be aware: concurrent modification of i
const entry = data[pos];
results[pos] = await task(entry);
}
}

const runners = Array.from({ length: runnerCount }, runner);

return Promise.all(runners).then(() => results);
}

To be used as:

  const delay = ms => new Promise(res => setTimeout(res, ms));

inParallel(async time => {
console.log(`Timer for ${time}ms starts`);
await delay(time);
console.log(`Timer for ${time}ms ends`);
}, [5000, 6000, 1000]/*ms*/, 2/*in parallel*/);


Related Topics



Leave a reply



Submit