iOS7のSafariでのREST APIの挙動について

清水と申します。

お聞きしたいことがあり、質問させて頂きます。

現在、REST APIを使用して、レコードの追加/更新を行うPGを作成しています。

そこで、動作確認を行った所、
IE9 ⇒ OK(エラーもなし)
FF ⇒ OK(エラーもなし)
Chrome ⇒ OK(エラーもなし)
PC版Safari ⇒ OK(エラーもなし)
iOS8のiPadのSafari ⇒ エラーは出るが、登録更新は可能
iOS7のiPadのSafari ⇒ エラーも出るし、登録更新が出来ない

という結果となりました。
iPadでの運用が必要なPGのため、上記の現象を解決したいと考えております。

何か、少しでもご助言を頂きたく、よろしくお願い致します。

こんにちは。

一見すると不思議な感じですね。まず、iPadであればパソコンと同じビューで動いていると思います。ここで、PC版(Windows?)Safariで問題なく、iOSのバージョンでも違いが出るとは気持ち悪いですね。

幾つか確認させて頂ければと思いますが、
・kintoneのJavaScript中からのREST APIリクエストかと思いますが、リクエスト時の関数は何をご利用でしょうか?(xmlHttpRequest、kintone.api等)
・エラーのメッセージはどのようなものが出力されていますでしょうか?

もしくは、差し支えなければ引っかかっている部分のスニペットでも貼付けて頂くと、解決まで早いかもしれません。

Ryu Yamashita様

お返事頂き、ありがとうございます。
動作確認をさらに進めました。
Windows版Safari(5.1.7) ⇒ エラーも出るし、登録更新が出来ない
Mac版Safari(7.0.5) ⇒ OK(エラーもなし)
という結果となりました。

また、ご質問頂いた件について、以下となります。

・kintoneのJavaScript中からのREST APIリクエストかと思いますが、リクエスト時の関数は何をご利用でしょうか?(xmlHttpRequest、kintone.api等)
⇒kintone.apiを使用しています。

・エラーのメッセージはどのようなものが出力されていますでしょうか?
⇒エラーメッセージは特に何も出力されておりません。。

以下にソースの一部を貼り付けます。ご確認頂けると幸いです。
不足している場合、言ってください。


インサートレコード用JSON文字列作成

function InsertObj(strShopcd,strShopnamego,strShopname,strEmpcd,strEmpname,time,strhon,strnyu){
var sql = ‘’;
sql += ‘{“日付”’ + ‘:{“value”:"’ + GetDay() +‘"},’;
sql += ‘“店コード”’ + ‘:{“value”:"’ + strShopcd +‘"},’;
sql += ‘“出勤店舗名”’ + ‘:{“value”:"’ + strShopnamego +‘"},’;
sql += ‘“所属店舗名”’ + ‘:{“value”:"’ + strShopname +‘"},’;
sql += ‘“社員CD”’ + ‘:{“value”:"’ + strEmpcd +‘"},’;
sql += ‘“社員名”’ + ‘:{“value”:"’ + strEmpname +‘"},’;
sql += ‘"’+ strhon + ‘"’ + ‘:{“value”:"’ + time +‘"},’;
sql += ‘"’+ strnyu + ‘"’ + ‘:{“value”:"’ + time +‘"}}’;
return sql;
};


データ登録箇所(一部抜粋)

//新規登録用JSON文字列作成
sql = InsertObj(
strShopcd,
strShopnamego,
strShopname,
strEmpcd,
strEmpname,
time,
strhon,
strnyu);

//文字列をJSONオブジェクトへパース
sqlobj = JSON.parse(sql);
//オブジェクトに追加
objJSONs.push(sqlobj);
//新規登録処理
kintone.api(
‘/k/v1/records’,
‘POST’,
{app:appIdmyself,records:objJSONs},
function(resp) {},
function(resp) {
var errmsg = ‘レコード登録時にエラーが発生しました。’;
// レスポンスにエラーメッセージが含まれる場合はメッセージを表示する
if (resp.message !== undefined){
errmsg += resp.message;
}
alert(errmsg);
}
);

K.Shimizuさん

私の手元の環境でSafari5.1.7(Windows8.1)というのがありましたので、ちょっと試行させて頂きました。結果記載頂いたスニペットそのままでレコード登録出来ています。以下は、シンプルに試験するために置き直したものです。アプリIDだけ変更頂ければ一覧画面表示でレコード登録されると思いますので、そのままコピペでお試し頂けませんでしょうか。(乱暴な作りですが)

kintone.api()実行時のレスポンスをエラーコンソールに表示する行を追加していますので、チェック頂ければと思います。200で成功時にもidsやrevisionsが返ると思います。

(function () {
“use strict”;

function InsertObj(strShopcd,strShopnamego,strShopname,strEmpcd,strEmpname,time,strhon,strnyu){
    var sql = '';
    sql += '{"日付"' + ':{"value":"' + '2014-09-23' +'"},'; // 日付フィールド
    sql += '"店コード"' + ':{"value":"' + strShopcd +'"},'; // 文字列一行フィールド
    sql += '"出勤店舗名"' + ':{"value":"' + strShopnamego +'"},'; // 文字列一行フィールド
    sql += '"所属店舗名"' + ':{"value":"' + strShopname +'"},'; // 文字列一行フィールド
    sql += '"社員CD"' + ':{"value":"' + strEmpcd +'"},'; // 文字列一行フィールド
    sql += '"社員名"' + ':{"value":"' + strEmpname +'"},'; // 文字列一行フィールド
    sql += '"'+ strhon + '"' + ':{"value":"' + time +'"},'; // 文字列一行フィールド
    sql += '"'+ strnyu + '"' + ':{"value":"' + time +'"}}'; // 文字列一行フィールド
    return sql;
};

kintone.events.on('app.record.index.show', function(event){

   var sql = InsertObj(

‘strShopcd’,
‘strShopnamego’,
‘strShopname’,
‘strEmpcd’,
‘strEmpname’,
‘time’,
‘strhon’,
‘strnyu’);

var sqlobj = JSON.parse(sql);
//console.log(sqlobj);

var objJSONs = [];

objJSONs.push(sqlobj);
//console.log(objJSONs);

kintone.api(‘/k/v1/records’, ‘POST’, {app:618,records:objJSONs}, function(resp) {
console.log(resp); // 成功時にもレスポンスをコンソールに表示(山下追記)
},function(resp) {
var errmsg = ‘レコード登録時にエラーが発生しました。’;
// レスポンスにエラーメッセージが含まれる場合はメッセージを表示する
if (resp.message !== undefined){
errmsg += resp.message;
}
alert(errmsg);
});
}); // kintone.events

})();

補足させて頂きますと、こちらにブラウザ対応の記載がありますが、
iOS7 Safariは一応対象ですし、問題なく動くのではないかと思います。

https://www.cybozu.com/jp/service/requirements.html

iOS8とWindowsのSafariは保証範囲外ということになり、実運用時には自己責任になろうかと思いますので、ご注意ください。

Ryu Yamashita様

スニペットから、検証を行って頂き、ありがとうございます。

貼り付けて頂いたソースを実行した所、iOS7のSafariで
問題なく動作することを確認致しました。

今一度、私の記述したPGを確認し、差分をチェック致します。

おまけ的なところで、気持ちですが

kintone.api(‘/k/v1/records’, ‘POST’, {app:618,records:objJSONs}, function(resp) {

の行のappやrecordsは(ダブル)クウォテーションで括っておく方がしっくりくる感じがします。

また、ご存知かもしれませんが、https://cybozudev.zendesk.com/hc/communities/public/questions/200769210

で紹介されているiOSデバイスのデバッグ方法は便利ですので、環境をお持ちであれば活用頂くと良いと思います。

Ryu Yamashita様

表題の件について、その後調査を行い、原因がおそらくわかりました。

今回、登録処理後、一覧画面へ遷移するという処理を入れていたのですが、
それが原因ということがわかりました。

登録処理後、2秒経ったら一覧画面へ遷移するという記述をしたところ、
エラーが発生しませんでした。

表題の件についてのエラーの原因は解決しましたので、
次は、如何にして登録/更新が完了したかを判定し、
一覧画面へ遷移させるかを検討致します。

親身になり、ご相談に乗って頂き、誠にありがとうございました。

また、何かありましたら、質問させて頂くかと思いますので、
その際は、何卒よろしくお願い致します。

K.Shimizuさん、解決されたようで良かったです(^^) kintone.api()は非同期ということを認識しつつ、上手くやりたいものですね。私も公式で提供されている関数の利用に努めますが、やむを得ない時にははみだします(^^;

またお目にかかりましょう(^^)

私の環境でも同じような現象がありました。
PC(Windows)では更新がうまくいくのですが、iPadのSafari上ではうまくいかない。
私の場合は一覧上に設置したボタンを押すと、該当レコードのある項目を更新するというものでした。
APIで更新(PUT)した後に
location.reload(true);
で一覧画面を更新してあげる、というロジックを入れておりましたが、iPadのSafariではなぜか更新ができませんでした。
上記をヒントに、
location.reload(true);
をPUTが成功した後の
function(resp)
の中に記載したところ、iPadのSafariでもうまく動作しました。
ご参考まで

tamakeyさん

 

事象の共通点としては、非同期処理に対する不適切な処理ながらたまたまうまくいったケースと、不適切さが顕在化したケースがデバイスや環境条件の違いによってこれまたたまたま顕在化したという感じです。非同期処理に対しては、コールバックやPromiseを利用して適切に対応すれば、このような事象を引き起こすことは起きえないというのが実の所です。

 

**K.Shimizu **さんのケースでは、「登録処理後に実は画面遷移を入れていました。」ということでしたが、登録処理そのものが非同期処理のため、そもそも登録処理「後」という動作が担保されないまま画面遷移処理するように記述してしまっていたという感じです。最終的にタイマーで対応されていますが、本来はtamakeyさんがやられたようにコールバック(もしくはPromise)で登録処理が終わった後に次の処理にいくことを担保するよう記述する必要があります。

ですよね。
私もこの非同期処理を考慮せずにソースを書いて、期待した順番にPostされなかったり、他アプリへのPut修了を前提とした処理が空振りになったり、他にも痛い目にあいました。
それが、デバイスの環境によって顕著化したりしなかったりというのは想定外だったのですが、なんにしても、
Ryu Yamashitaさんの仰る通り『処理終了を担保する』ということを今回あらためて肝に銘じました。

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。