2017-07-28 5 views
0

Bluebird Promisesを使用してオブジェクトを構築して返したい。 Promiseは、オブジェクトに追加する追加データを取得するHTTP要求です。ForループでBluebird Promiseを使用してオブジェクトの配列を作成して返す

私は(私はまた、いくつかのミドルウェアを実行するフレームワークを使用しています - これはz.が何であるかである)forループの中に要求を実行する機能を作成し、この関数は、内部と呼ばれている

const getWebAppCustomFieldDetails = (z, url) => { 
    const responsePromise = z.request({ 
     url:url, 
     headers:{ 
      'content-type': 'application/json' 
     } 
    }); 
    return responsePromise 
    .then(response =>{ 
     return JSON.parse(response.content); 
    }); 
}; 

次のコード:

const webAppFields = (z, bundle) => { 
//This section carries creates an initial request which gets the bulk of the data 
const responsePromise = z.request({ 
    url: webAppUrl(bundle) + '/' + encodeURI(bundle.inputData.webApp), 
    headers:{ 
    'content-type': 'application/json' 
    }, 
}); 
//This is an array to hold the objects created from the response 
var fields = []; 
return responsePromise 
    .then(response => { 

    response = JSON.parse(response.content); 

    //From the response, append the core fields 
    response.systemFields.forEach(function (systemField) { 
     fields.push({ 
     'key': systemField.name, 
     'required': systemField.required, 
     'type': systemField.type.toLowerCase() 
     }); 
    }); 
    return response; 
    }) 
    .then(response => { 
    //Sometimes there are custom fields that need to be retrieved individually 
    const customFieldCount = response.fields.length; 
    var customFieldAppend = ''; 
    for (var i = 0; i < customFieldCount; i++){ 

     getWebAppCustomFieldDetails(z, response.fields[0].links[0].uri) 
     .then(response =>{ 
      customFieldAppend = { 
      'key': response.name, 
      'required': response.required, 
      'type': response.type.toLowerCase() 
      }; 
      //This push doesn't updated the fields array! 
      fields.push(customFieldAppend); 
     }); 
    } 
    //This return does not include the custom fields! 
    return fields; 
    }); 
}; 

私はあなたがを使用することができ、ネストされた約束

答えて

0

から値を返す方法を見つけ出すことはできませんあなたは、単一の約束にforループ内で作成された約束の一覧削減する:

... 
    .then(response => { 
     const customFieldCount = response.fields.length; 
     var customFieldAppend = ''; 

     // Promice.reduce will return the accumulator "totalFields" 
     return Promise.reduce(response.fields, (totalFields, field) => { 
      getWebAppCustomFieldDetails(z, field.links[0].uri) // Using the "field" variable provided by the reducer function 
          .then(response => { 
           customFieldAppend = { 
            'key': response.name, 
            'required': response.required, 
            'type': response.type.toLowerCase() 
           }; 
           // Add the data to the accumulator "totalFields" 
           totalFields.push(customFieldAppend); 
          }); 
     }, []); // The third argument is the initial value of the accummulator. In your example it is a an array, so the initial value is an empty array. 
    }); 
... 

Promise.reduceは、入力に3つの引数を取ります(response.fields)上のループへの引数のリスト、reducer機能と初期のアキュムレータの値。 (totalFieldsと呼ばれる)アキュムレータは、reducer関数の最初の引数です。リスト内の値を1つの値に減らすために使用される変数です。あなたのケースでは、アキュムレータは配列(例ではfields配列)です。そのため、初期値は空の配列です。

reduce関数内では、リストの1つの要素(2番目の引数)にアクセスすることができ、非同期操作を呼び出すことができ、アキュムレータ広告をすべてのステップに埋め込むことができます。 Promise.reduce関数は、約束の中にラップされたアキュムレータを返します。このため、関数はPromise.reduceの返された約束を直接返すことができます。

関連する問題