標準の拡張ポイントを提供するJavaScriptウィジェットがあります。そのうちの一つがbeforecreate
関数です。アイテムが作成されないようにするためにfalse
を返すべきです。
JQueryを使ってこの関数にAjax呼び出しを追加しました。
beforecreate: function (node, targetNode, type, to) {
jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
function (result) {
if (result.isOk == false)
alert(result.message);
});
}
しかし、私は自分のウィジェットがその項目を作成しないようにしたいので、コールバックではなくmother-functionにfalse
を返さなければなりません。 jQueryまたは他のブラウザ内APIを使用して同期AJAX要求を実行する方法はありますか?
jQueryのドキュメントから :同期Ajaxリクエストを取得するには、 Asynchronous オプションを false に指定します。そうすれば、あなたのコールバックはあなたのmother関数が進む前にデータを設定することができます。
提案されたように変更された場合、コードは次のようになります。
beforecreate: function (node, targetNode, type, to) {
jQuery.ajax({
url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
success: function (result) {
if (result.isOk == false) alert(result.message);
},
async: false
});
}
次のようにしてjQueryのAjax設定を同期モードにすることができます。
jQuery.ajaxSetup({async:false});
そしてjQuery.get( ... );
を使ってAjax呼び出しを実行します。
それからちょうどそれをもう一度回しなさい
jQuery.ajaxSetup({async:true});
@Adamで提案されているのと同じことがうまくいくと思いますが、jQuery.get()
やjQuery.post()
をもっと複雑なjQuery.ajax()
構文に再設定したい人には役に立つかもしれません。
優れた解決策!それを実装しようとしたときに気付いたのですが、success句に値を返すと、未定義の値が返されることになります。変数に格納してその変数を返す必要がありました。これが私が思いついた方法です。
function getWhatever() {
// strUrl is whatever URL you need to call
var strUrl = "", strReturn = "";
jQuery.ajax({
url: strUrl,
success: function(html) {
strReturn = html;
},
async:false
});
return strReturn;
}
これらの答えはすべて、async:falseを指定してAjax呼び出しを行うと、Ajax要求が完了するまでブラウザーがハングするという点を見逃しています。フロー制御ライブラリを使用すると、ブラウザを停止せずにこの問題を解決できます。これは Frame.js の例です。
beforecreate: function(node,targetNode,type,to) {
Frame(function(next)){
jQuery.get('http://example.com/catalog/create/', next);
});
Frame(function(next, response)){
alert(response);
next();
});
Frame.init();
}
function getURL(url){
return $.ajax({
type: "GET",
url: url,
cache: false,
async: false
}).responseText;
}
//example use
var msg=getURL("message.php");
alert(msg);
クロスドメインのAjax呼び出しを( _ jsonp _ を使用して)行っている場合 - you 同期できない は、jQueryではasync
フラグを無視します。
$.ajax({
url: "testserver.php",
dataType: 'jsonp', // jsonp
async: false //IGNORED!!
});
JSONP呼び出しの場合は、次のものを使用できます。
注:この警告メッセージが表示されるため、async: false
を使用しないでください。
Gecko 30.0(Firefox 30.0/Thunderbird 30.0/SeaMonkey 2.27)以降では、メインスレッド上の同期リクエストはユーザーエクスペリエンスに悪影響を与えるため非推奨になりました。
Chromeはコンソールでこれについて警告します:
メインスレッド上の同期XMLHttpRequestは、エンドユーザーのエクスペリエンスに悪影響を与えるため、推奨されません。詳細については、 https://xhr.spec.whatwg.org/ /を確認してください。
このようなことをしていると、これはあなたのページを壊す可能性があります。
まだ同期しているのにまだブロックしていないような感じでやりたいのなら、async/awaitとおそらく新しい Fetch APIのような約束に基づくajaxを使うべきです。
async function foo() {
var res = await fetch(url)
console.log(res.ok)
var json = await res.json()
console.log(json)
}
編集 chromeは/に取り組んでいます ページを閉じるときに同期XHRを許可しない ユーザーがページを移動したり閉じたりしているとき。これには、アンロード前、アンロード、ページ非表示、および可視性の変更が含まれます。
これがあなたのユースケースであるならば、あなたは navigator.sendBeacon を見たいと思うかもしれません
Httpヘッダーまたはiframeのallow属性のいずれかを使用して同期要求を無効にすることも可能です。
私はCarcioneから与えられた答えを使い、JSONを使うように修正しました。
function getUrlJsonSync(url){
var jqxhr = $.ajax({
type: "GET",
url: url,
dataType: 'json',
cache: false,
async: false
});
// 'async' has to be 'false' for this to work
var response = {valid: jqxhr.statusText, data: jqxhr.responseJSON};
return response;
}
function testGetUrlJsonSync()
{
var reply = getUrlJsonSync("myurl");
if (reply.valid == 'OK')
{
console.dir(reply.data);
}
else
{
alert('not valid');
}
}
dataType / 'JSON' を追加し、 .responseText を responseJSON に変更しました。
返されたオブジェクトの statusText プロパティを使用してステータスも取得しました。これはAjaxレスポンスのステータスであり、JSONが有効かどうかではありません。
バックエンドは正しい(整形式の)JSONで応答を返さなければなりません。そうでなければ返されるオブジェクトは未定義になります。
元の質問に答えるときに考慮する2つの側面があります。 1つはAjaxに( async:false を設定して)同期的に実行するように指示し、もう1つはコールバック関数ではなく呼び出し側関数のreturnステートメントを介して応答を返します。
私はPOSTでも試してみましたが、うまくいきました。
GETをPOSTに変更し、 data:postdata を追加しました
function postUrlJsonSync(url, postdata){
var jqxhr = $.ajax({
type: "POST",
url: url,
data: postdata,
dataType: 'json',
cache: false,
async: false
});
// 'async' has to be 'false' for this to work
var response = {valid: jqxhr.statusText, data: jqxhr.responseJSON};
return response;
}
上記のコードは async が false の場合にのみ機能することに注意してください。 async:true /返されるオブジェクト jqxhr は、AJAX呼び出しが戻った時点では有効ではありませんが、あとで非同期呼び出しが終了したときに限ります。 response 変数を設定するには遅すぎます。
async: false
を使えば、ブロックされたブラウザになります。ノンブロッキング同期ソリューションの場合は、次のものを使用できます。
ES6ではジェネレータと coライブラリ を使うことができます。
beforecreate: function (node, targetNode, type, to) {
co(function*(){
let result = yield jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
//Just use the result here
});
}
ES7では、asycを使うことができます。
beforecreate: function (node, targetNode, type, to) {
(async function(){
let result = await jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
//Just use the result here
})();
}
これは例です。
$.ajax({
url: "test.html",
async: false
}).done(function(data) {
// Todo something..
}).fail(function(xhr) {
// Todo something..
});
まず$ .ajaxを使うときと$ .get/$を使うときを理解する必要があります
リクエストヘッダの設定、キャッシュ設定、同期設定など、Ajaxリクエストを低レベルで制御する必要がある場合は、$。ajaxを使用してください。
$ .get/$。post:ajaxリクエストを低レベルで制御する必要がない場合。単純にデータをサーバーに取得/投稿します。の省略形です
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType
});
したがって、他の機能(同期、キャッシュなど)を$ .get/$。postで使用することはできません。
したがって、Ajaxリクエストに対する低レベルの制御(同期、キャッシュなど)の場合は、$。ajaxを使用する必要があります
$.ajax({
type: 'GET',
url: url,
data: data,
success: success,
dataType: dataType,
async:false
});
XMLHttpReponse
同期操作は推奨されないため、XMLHttpRequest
をラップする次のような解決策を思いつきました。これにより、本質的に非同期でありながら、AJAXクエリを順番に並べることができます。これは使い捨てのCSRFトークンには非常に便利です。
また、透過的なので、jQueryなどのライブラリはシームレスに動作します。
/* wrap XMLHttpRequest for synchronous operation */
var XHRQueue = [];
var _XMLHttpRequest = XMLHttpRequest;
XMLHttpRequest = function()
{
var xhr = new _XMLHttpRequest();
var _send = xhr.send;
xhr.send = function()
{
/* queue the request, and if it's the first, process it */
XHRQueue.Push([this, arguments]);
if (XHRQueue.length == 1)
this.processQueue();
};
xhr.processQueue = function()
{
var call = XHRQueue[0];
var xhr = call[0];
var args = call[1];
/* you could also set a CSRF token header here */
/* send the request */
_send.apply(xhr, args);
};
xhr.addEventListener('load', function(e)
{
/* you could also retrieve a CSRF token header here */
/* remove the completed request and if there is more, trigger the next */
XHRQueue.shift();
if (XHRQueue.length)
this.processQueue();
});
return xhr;
};
これはjQueryを使ったASYNCリクエストのための私の簡単な実装です。これが誰にでも役立つことを願っています。
var queueUrlsForRemove = [
'http://dev-myurl.com/image/1',
'http://dev-myurl.com/image/2',
'http://dev-myurl.com/image/3',
];
var queueImagesDelete = function(){
deleteImage( queueUrlsForRemove.splice(0,1), function(){
if (queueUrlsForRemove.length > 0) {
queueImagesDelete();
}
});
}
var deleteImage = function(url, callback) {
$.ajax({
url: url,
method: 'DELETE'
}).done(function(response){
typeof(callback) == 'function' ? callback(response) : null;
});
}
queueImagesDelete();
これは私の“ Thread ”名前空間です。
var Thread = {
sleep: function(ms) {
var start = Date.now();
while (true) {
var clock = (Date.now() - start);
if (clock >= ms) break;
}
}
};
そしてこれが私の呼称です。
var d1 = new Date();
console.log('start ' + d1.toLocaleTimeString());
Thread.sleep(10000);
var d2 = new Date();
console.log('end ' + d2.toLocaleTimeString());
コンソールを見ると、次のようになります。
start 1:41:21 PM
end 1:41:31 PM