新規投稿
フォローする

Promiseでループするためにmapを使っているのですがpendingとなってしまい実装できません

下記のようなコードで

1. Aアプリの一覧画面で500件までの$idと["商品名"]を取得してmapを使用し配列に格納します。

2. 次の1.で取得した["商品名"]をkeyにして異なるBアプリよりGETして数量を合計したsumをmapを使用してそれぞれ取得します。

ーーーここまでは意図した動作をしています

3.ここでresultAryで2.の結果を取得しAアプリにもどってPUTしようとしたところ、resultAryのPromiseオブジェクトが全てPendingとなってしまい、得られた結果をAアプリにPUTできません。

Promiseではfor文などでループできないことを知りmap()を使用してここまで来たのですが、問題点と解決方法について、アドバイス願えますでしょうか。

※ざっくりした具体的なイメージ

Aアプリ

id :1 , 動物フィールド:0個

id:2 , 魚フィールド:0個

Bアプリ

id1 : 動物フィールド:2個

id2 : 動物フィールド:3個

id:3 , 魚フィールド:5個

id:4 , 魚フィールド:5個

→Bアプリから動物は5個、魚は10個である結果(sum)は取得できている

これに基づき、AアプリをPUTして

id :1 , 動物フィールド:5個

id:2 , 魚フィールド:10個

にしたいのですが、resultAryでpendingとなり、うまく更新がかけられないという状況です。

(function() {
"use strict";

var idAry = []
var nameAry = []
var sumAry = []
var resultAry = []
kintone.events.on('app.record.index.show', function(event){
if(document.getElementById('updateButton') !== null) return;
var button = document.createElement('button');
button.innerHTML = '一括更新';
button.id = 'updateButton';
kintone.app.getHeaderMenuSpaceElement().appendChild(button);
button.addEventListener('click', function(){
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', {
app: 449,
query: 'limit ' + 500 +' offset ' + 0
})
.then(function(response){
idAry = response.records.map(function(item){
return item.$id.value
})
nameAry = response.records.map(function(item){
return item['商品名'].value
})
})
.then(function(){
resultAry = nameAry.map(function(item){
var query = 'p1="' + item + '"';
var body = {
'app' : 390,
'query' : query
};
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body)
.then(function(resp){
var sum = 0;
resp.records.forEach((record)=>{
sum += record['関連レコード一覧数量'].value ? parseInt(record['関連レコード一覧数量'].value) : 0;
});
return sum
//console.log(sum)
})

})

}).then(function(){
console.log(resultAry)//ここでPromiseOBJがPendingとなるため、下の処理に移れない
idAry.map(function(){
//ここでAアプリのidの順番にsumで得られた数値をPUTで更新していきたい
})
});
return event;
});
})();
0

4件のコメント

Avatar
江田篤史

ryoryoさん

Promise.all()を使うと良いです.
Promiseの配列をまとめて1つのPromiseにしてくれます.

...
.then(function(){ //27行目
  return Promise.all(nameAry.map(function(item){
    var query = 'p1="' + item + '"';
    ...
  })
}).then(function(resultAry){ //46行目
  console.log(resultAry)
  ...
})
1
Avatar
ryoryo

コメントありがとうございます。実装することができました。

感覚的に不思議でお尋ねしたいのです、Docsでも内容を確認する限りPromise.all()は複数のPromiseオブジェクトを引数とすることで纏めて非同期的に解決するメソッドであると理解しております。

 

これを本件に照らして観察した場合、

//前略

.then(function(){
return Promise.all(nameAry.map(function(item){
var query = 'p1="' + item + '"';
var body = {
'app' : 390,
'query' : query
};
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body)
.then(function(resp){
var sum = 0;
resp.records.forEach((record)=>{
sum += record['関連レコード一覧数量'].value ? parseInt(record['関連レコード一覧数量'].value) : 0;
});
return sum
})

}))

}).then(//後略

のように、一つのPromiseオブジェクトしか処理していないように思えるのですが、これは感覚的な間違いでmapを使用していることでそれぞれが結果が複数のオブジェクトとして配列で返されているため、全てを纏めて解決するためにPromise.all()で処理する必要があるということでしょうか?

 

宜しくお願い申し上げます。

0
Avatar
江田篤史

ryoryoさん

› mapを使用していることでそれぞれが結果が複数のオブジェクトとして配列で返されているため、全てを纏めて解決するためにPromise.all()で処理する必要がある

仰る通りです。
今回の例でmapが返しているのは、1つのPromiseオブジェクトではなく、複数のPromiseオブジェクトをまとめた1つの配列になります。

1
Avatar
ryoryo

ご返信ありがとうございます。

全て理解することができました。お力添えに御礼申し上げます。

1
サインインしてコメントを残してください。