I wrote this piece of code where I get the Json from an ajax call. I need to handle the response (success, error) with javascript promise (resolved after 2 seconds) and .then() method. I read a few stuff online but don't know where to begin. Can anybody help me please? Thanks
function jsonResult(spaceName){
var baseUrl = "BaseUrl";
$.ajax({
url:baseUrl + "/api/request/url",
type:"GET",
dataType: "json",
error: function(xhr,status,error) {
console.log(JSON.stringify(error));
},
success: function(response){
getResult(response)
}
});
}
You just need to update your function to return a promise and then in your success and error methods just call resolve and reject respectively. Here is a sample pulled from MDN:
function myAsyncFunction(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(xhr.statusText);
xhr.send();
});
}
You can read more on this here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Here is a simple implementation of your example code:
function jsonResult(spaceName){
var baseUrl = "BaseUrl";
return new Promise((resolve, reject) => {
$.ajax({
url:baseUrl + "/api/request/url",
type:"GET",
dataType: "json",
error: function(xhr,status,error) {
reject(JSON.stringify(error));
},
success: function(response){
resolve(response);
}
});
});
}
You can user return a promise on calling this function which will resolve in success callbacka and will be rejected in error callback like this
function jsonResult(spaceName){
var baseUrl = "BaseUrl";
return new Promise((resolve, reject) => {
$.ajax({
url:baseUrl + "/api/request/url",
type:"GET",
dataType: "json",
error: function(xhr,status,error) {
console.log(JSON.stringify(error));
reject(error);
},
success: function(response){
resolve(getResult(response));
}
});
}
}
// Usage
jsonResult(someInput).then(response => {
// success
})
.catch(error => {
// error
});
jQuery 3.0 is Promises/A+ compatible so just remove the error/success and do the then/catch
function jsonResult(spaceName) {
var baseUrl = "BaseUrl";
$.ajax({
url:baseUrl + "/api/request/url",
type:"GET",
dataType: "json"
}).then(console.log, console.error)
}
alternativ is the the native fetch api...
fetch(baseUrl + "/api/request/url")
.then(res => res.json())
.then(console.log)
Related
I have this function to delete items once a popup returns true:
function deleteItems(selectedItems){
if (selectedItems.length > 0) {
$("#confirm-popup-modal").modal("show");
$("#confirm-popup-modal").one('hidden.bs.modal', function (event) {
if ($("#confirm-modal").val() == "true") {
var form_data = selectedItems;
$.ajax({
url: "#Url.Action("Delete", #ViewContext.RouteData.Values["controller"].ToString())",
method: "POST",
data: JSON.stringify(form_data),
contentType: "application/json",
success: function (result) {
if (result.Result == true) {
var deleteId = result.Output;
await CompletedJobsAccess(deleteId);
table.draw();
}
},
error: function (error) {
console.log(error);
}
});
}
});
}
}
Inside the Ajax success is another function called CompletedJobsAccess that will keep looping every 3 seconds to check if a job deletion has been completed:
function CompletedJobsAccess(DeleteId){
return new Promise((resolve,reject)=>{
var loopInterval = setInterval(function() {
$.ajax({
url: "#Url.Action("Verify", "CompletedJobsAccess", new {area="Base" })",
method: "POST",
data: JSON.stringify(DeleteId),
contentType: "application/json",
success: function(verifyResult) {
if (verifyResult.IS_COMPLETED == true && verifyResult.IS_PROCESSING == false) {
if (verifyResult.IS_SUCCESSFUL == true) {
console.log(verifyResult.OUTPUT);
$.each($.parseJSON(verifyResult.OUTPUT), function(index, value) {
if (value.Result == true) {
toastr.success(value.Message);
}else{
toastr.error(value.Message);
}
});
clearInterval(loopInterval);
} else {
toastr.error(verifyResult.ERROR_MESSAGE);
}
}
},
error: function(innerError) {
console.log(innerError);
}
});
}, 3000);
});
}
However, when I load the page, and call deleteItems(selected);, this is the error I get:
Uncaught SyntaxError: await is only valid in async functions and the
top level bodies of modules
I tried searching around but I can't find if it can work within an ajax success function.
EDIT:
Added async to the ajax success function but the table draw function doesn't run.
function deleteItems(selectedItems){
if (selectedItems.length > 0) {
$("#confirm-popup-modal").modal("show");
$("#confirm-popup-modal").one('hidden.bs.modal', function (event) {
if ($("#confirm-modal").val() == "true") {
var form_data = selectedItems;
$.ajax({
url: "#Url.Action("Delete", #ViewContext.RouteData.Values["controller"].ToString())",
method: "POST",
data: JSON.stringify(form_data),
contentType: "application/json",
success: async function (result) {
if (result.Result == true) {
var deleteId = result.Output;
console.log("table before");
await CompletedJobsAccess(deleteId);
console.log("table draw");
table.draw();
}
table.draw();
},
error: function (error) {
console.log(error);
}
});
}
});
}
}
EDIT 2: Updated CompletedJobsAccess to resolve promises:
function CompletedJobsAccess(DeleteId){
return new Promise((resolve,reject)=>{
var loopInterval = setInterval(function() {
$.ajax({
url: "#Url.Action("Verify", "CompletedJobsAccess", new {area="Base" })",
method: "POST",
data: JSON.stringify(DeleteId),
contentType: "application/json",
success: function(verifyResult) {
if (verifyResult.IS_COMPLETED == true && verifyResult.IS_PROCESSING == false) {
if (verifyResult.IS_SUCCESSFUL == true) {
console.log(verifyResult.OUTPUT);
$.each($.parseJSON(verifyResult.OUTPUT), function(index, value) {
if (value.Result == true) {
toastr.success(value.Message);
}else{
toastr.error(value.Message);
}
});
clearInterval(loopInterval);
return Promise.resolve();
} else {
toastr.error(verifyResult.ERROR_MESSAGE);
return Promise.resolve();
}
}
},
error: function(innerError) {
console.log(innerError);
}
});
}, 3000);
});
}
Just make the success function async
$.ajax({
url: "https://jsonplaceholder.typicode.com/users/3",
method: "GET",
success: async function(data) {
console.log("first - now wait a second ...");
await new Promise((res) => setTimeout(res, 1000));
console.log("second, data:",data);
},
error: function(innerError) {
console.log(innerError);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Working JSFiddle (can't work on this site because of CORS)
In CompletedJobsAccess(DeleteId) you return a promise. But the way you set it up it will never execute the resolve function. So your await will wait forever ...
You could place the line
resolve();
right after
clearInterval(loopInterval);
in your CompletedJobsAccess function to make it work.
Do not return yet another Promise.resolve() like you did in your edited code.
A resolve function for a promise is never returned but executed.
Try Adding async before all the function keyword like async function deleteItems(selectedItems){ and also $("#confirm-popup-modal").one('hidden.bs.modal', async function (event) { and it should do the job.
You're using await in functions that don't use the async keyword. await isn't available in regular functions. To solve this, you can change all the functions using await to async function to make it into an asynchronous function.
And if you don't want want to go through every function to make it asynchronous, you can just put the entire code inside an asynchronous IIFE
What is the easiest way to convert an image read via ajax-jquery to base64?
I found this solution on stackoverflow but it doesn't work, so I guess the solution is wrong.
$.ajax({
url: "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png",
type: "GET",
crossDomain: true,
success: async function(result, textStatus, jqXHR){
// I want the base64 encoded version of my img
console.log(btoa(unescape(encodeURIComponent(result))))
}, // success
error: function(xhr, status){
reject(img_url)
} // error
})
Try this, it works for me:
return new Promise((resolve, reject) => {
$.ajax({
url:'YOUR_URL',
cache:false,
xhr:function(){
var xhr = new XMLHttpRequest();
xhr.responseType= 'blob'
return xhr;
},
success: function(data){
var reader = new FileReader()
reader.onload = () => resolve(reader.result)
reader.onerror = reject
reader.readAsDataURL(data);
},
error:function(){
}
})
}
Here is a simplified of my code:
var res = array();
$.ajax({
url: 'test1.php',
async: true,
success: function (data) {
res[1] = data.result;
}
});
$.ajax({
url: 'test2.php',
async: true,
success: function (data) {
res[2] = data.result;
}
});
if ( /* both ajax request are done */ ) {
// do stuff
} else {
// wait
}
As you can see I've used async: true to run those ajax requests at the same time (in parallel). Now I need to wait until both requests done. How can I determine an ajax request is done? If not wait until it get done?
You can use promises:
Promise.all([
$.ajax({ url: 'test1.php' }),
$.ajax({ url: 'test2.php' })
])
.then(([res1, res2]) => {
// Both requests resolved
})
.catch(error => {
// Something went wrong
});
You can use callback function as well.
var res = [];
function addResults(data) {
res.push(data);
console.log('Request # '+res.length);
if ( res.length >= 2 ) {
// do stuff
console.log('both request has done.');
} else {
// wait
}
}
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts',
success: function (data) {
addResults(data);
}
});
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts',
success: function (data) {
addResults(data);
}
});
Use Promise.all function. It will be resolved if all of the promises is resolved and pass the data as array to the then function, else it will be rejected with the first promise failure value
Promise.all([
$.ajax({ url: 'test1.php'}),
$.ajax({ url: 'test2.php'})
])
.then(results => {
// results is an array which contains each promise's resolved value in the call
})
.catch(error => {
// The value of the first rejected promise
});
this official document could help you.
http://api.jquery.com/ajaxStop/
example:
var res = [];
$.ajax({
url: 'test1.php',
async: true,
success: function (data) {
res.push('Ajax one is complete');
}
});
$.ajax({
url: 'test2.php',
async: true,
success: function (data) {
res.push('Ajax two is complete');
}
});
var resALL = function(){
console.log(this)
}
//After the requests all complete
$(document).ajaxStop(resALL.bind(res))
I have to make an async call which uses cookie to get bearer token which has to be passed to make actual ajax call for the resource.
And I have written the following code which works awesome and get's me the result.
Can I use ajaxPrefilter or beforeSend options to get the tokens, I tried to find documentation for ajaxPrefilter which says it accepts a function, but does that waits for that function to be finished before making actual call?
Token retrieval function
function getTokenUsingCookieAsync() {
return new Promise(function (resolve, reject) {
$.ajax('/retrieve-token').done(function (result) {
resolve(result.token);
}).fail(function (message) {
reject(message);
});
});
}
Actual execute function:
function execute(url, method, data) {
var deferred = $.Deferred();
getTokenUsingCookieAsync().then(function (response) {
var reqSettings = {
async: true,
url: url,
cache: false,
type: method,
headers: {
Authorization: 'Bearer '+ response,
},
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: data ? JSON.stringify(data) : null
};
$.ajax(reqSettings).done(function (result) {
deferred.resolve(result);
}).fail(function (message) {
deferred.reject(message);
});
}).catch(function (message) {
deferred.reject(message);
});
return deferred.promise();
}
So the following pseudo code is possible or not?
$.ajaxPrefilter((options) => {
$.ajax('/retrieve-token').done((result) => {
options.headers = {
Authorization: `Bearer ${result}`
};
});
});
$.ajax('actual-url')
.done(whatever);
I am trying to wrap Ajax into a Bluebird promise wrapper, but am receiving:
Error: Unhandled rejection (stack trace here...)
wrapper1.js
let fetch = require('./wrapper2');
function requestWeb(type, url, data) {
return new Promise(function(resolve, reject) {
url = config.serverUrl + url.trim();
let options = {
type: type,
data: data ? JSON.stringify(data) : null,
dataType: 'json',
contentType: 'application/json',
crossDomain: true,
timeout: 15000,
xhrFields: { withCredentials: true }
};
fetch(url, options)
.then(data => {
resolve(data);
})
.catch(err => {
console.log('web api error: ' + err.message);
notify('Please check your interet connection');
reject(err);
});
});
}
wrapper2.js
import Promise from 'bluebird';
export default function(url, options) {
return new Promise(function(resolve, reject) {
$.ajax(url, options)
.done((result) => {
resolve(result);
})
.fail((xhr, err) => {
let proxy = new Error();
proxy.message = err || 'error is null';
proxy.name = 'ajax error';
reject(proxy);
});
});
}
Please note Bluebird requires different error object on reject().
I figured it out, BlueBird wants to warn you that a reject() call has been fired but you are not catching it. So I was using...
requestWeb(type, url, data).then((result)=>{});
So to fix, do one of two things: add the .catch() to the end of the call, or remove the reject(err) from the promise.