2017-09-17 9 views
0

私はそれらについて今日学んだので、Promisesでこれを行う方法を理解できません。JavaScript内の各要素に非同期関数を適用するPromise

  • も行わ配列(JSONオブジェクトの配列に(私はこれを行うことができます)
  • を連結応答エレメントをGETリクエストを送信し、最後のページに到達するまで繰り返す:私は何をしようとしていることということですそのような画像のアップロードやデータベースクエリとして非同期操作を実行し、この配列の各要素について)
  • 、(ここで立ち往生)

ここで私がこれまで行っているものです:それは

を機能後すべてのページにわたって起こります。

function handleCountry(country, callback) { 
    // do stuff here 
    if (!country["extra"]) { 
    app.models.Country.upsert(countryJson, callback); 
    } else { 
    // do async stuff here, image upload etc with Async.auto 
    Async.auto({ 
     'uploadImage': (autoCallback) => { 
     uploadImage(autoCallback); 
     } 
     'updateOnDb': ['uploadImage', (results, autoCallback) => { 
     // do stuff 
     app.models.Country.upsert(countryJson, autoCallback); 
     } 
    }, callback); 
    } 
} 

私はここで何を実行する必要があります。

ここ
getAllCountries(formattedLink, pageNr) 
    .then((countries) => { 
    // will call handleCountry method for each country here 

    // how do I handle the callback to/from handleCountry here? 
    // that is wrong 
    // countries.map(handleCountry); 
    }) 
    .then(() => { 
    console.log('Handled all countries'); 
    return res.sendStatus(200); 
    }) 
    .catch((error) => { 
    console.log(error); 
    return res.sendStatus(500); 
    }); 

がhandleCountry機能がどのようにある:ここでは

function getAllCountries(requestURL, pageNr, countries) { 
    return Request({ 
    'method': 'GET', 
    'uri': requestURL, 
    'json': true, 
    }).then((response) => { 
    if (!countries) { 
     countries = []; 
    } 

    countries = countries.concat(response.data); 
    const meta = response.meta; 

    if (pageNr < meta['pagination']['total_pages']) { 
     pageNr += 1; 
     let formattedLink = Format(BASE_URL, API_TOKEN, pageNr); 
     return getAllCountries(formattedLink, pageNr, countries); 
    } 

    return countries; 
    }); 
} 

は、私は問題を抱えていますどこにあるのでしょうか?ところで、国を扱う順番は重要ではありません。私たちはすべての約束のために完了するためにコールバックをバインドすることができます私たちは、アレイ内の各強いため約束それらを作成するすべての国を取得し、最終的にpromise.allにそれらを通過した後

+0

代わりに 'handleCountry'が約束を返すようにするだけです。' return Promise.all(countries.map(handleCountry)); 'を実行するだけです。これは役に立ちます:[既存のコールバックAPIを約束に変換するにはどうすればいいですか?](https://stackoverflow.com/q/22519784/218196) –

答えて

0
function getAllCountries(requestURL, pageNr, countries) { 
    Request({ 
     'method': 'GET', 
     'uri': requestURL, 
     'json': true, 
    }).then((response) => { 
     if (!countries) { 
     countries = []; 
     } 

     countries = countries.concat(response.data); 
     const meta = response.meta; 

     if (pageNr < meta['pagination']['total_pages']) { 
      pageNr += 1; 
      let formattedLink = Format(BASE_URL, API_TOKEN, pageNr); 

      // declaring array to be passed inside promise.all 
      let countriesPromises = []; 


      // creating promises for each country 
      countries.forEach(function(country) { 
       countriesPromises.push(new Promise(function(){ 
        handleCountry(country,callback); 
       }) 
      }); 

     } 

     // callback for all countries. 
     Promise.all(countriesPromises) 
      .then(() => { 
       console.log('Handled all countries'); 
       return res.sendStatus(200); 
      }) 
      .catch((error) => { 
       console.log(error); 
       return res.sendStatus(500); 
      }) 
    } 

} 

()。私はすべてのリターンステートメントを削除し、getAllCountriesはもはや有効ではないことに注意してください。私たちはgetAllCountriesの中にコールバックを実装しています。必要に応じてそれを分けることができます。

0

問題はhandleCountryAsync()が「約束のゲーム」をプレイしていないということです。約束を返す代わりにコールバックを受け入れます。

あなたはhandleCountry()を書き換えることによりpromisifyでしたが、それはそのままhandleCountry()を残し、アダプタを書くために同じように簡単です、handleCountryAsync()次のように:

function handleCountryAsync(country) { 
    return new Promise((resolve, reject) => { 
     try { 
      handleCountry(country, (...args) => { 
       resolve(args); // promises can be fulfilled only with a single value, but multiple arguments can be delivered as an array. 
      }); 
     } 
     catch(error) { 
      reject(error); 
     } 
    }); 
} 

を今、より高レベルのコードで明白なコールバックの必要性は消え、 countries.map()Promise.all()に約束の配列を返すことができます。aywayそれの本質だ

getAllCountries(formattedLink, pageNr) 
.then(countries => Promise.all(countries.map(handleCountryAsync))) 
.then(() => { 
    console.log('Handled all countries'); 
    return res.sendStatus(200); 
}) 
.catch((error) => { 
    console.log(error); 
    return res.sendStatus(500); 
}); 

を。他の考慮事項は、主にエラー処理に関するものです。たとえば、エラーを呑み込むか、またはhandleCountryAsyncが1つ失敗して500を発生させるかどうかは、設計上の決定です。上記のように、後者があります。

関連する問題