简体   繁体   中英

how to use async/await inside promise

I want to use async/await inside this promise.allSettled to convert currency by fetching some api or databased stored currency rates.

like i want to use await here like this, but not sure where to put async.

arrcars["price_client"] = await forexService.convertCurrency(item.regular_price, "EUR", userCurrency);

I have posted my entire code. need some guidance here.

This is controller

    const httpStatus = require('http-status');
    const pick = require('../utils/pick');
    const catchAsync = require('../utils/catchAsync');
    const async = require('async');
    const axios = require('axios');
    const { talixoService } = require('../services');
    const { iwayService } = require('../services');
    const { forexService } = require('../services');
    
        const searchCars = function (req, res) {
            const talixoData = talixoService.findTalixoCars(req.body) //call talixo api in services
            const iwayData = iwayService.findiWayCars(req.body) //call iwaytransfers api in services
        
            if (req.query.usercurrency) {
                var userCurrency = req.query.usercurrency;
            } else {
                var userCurrency = "INR";
            }
        
            return Promise.allSettled([talixoData, iwayData]).then(([restalixo, resiway]) => {
                const taxiresults = [];
                if (restalixo.status === "fulfilled") {
                    //console.log(restalixo.value.data);
                    if (restalixo.value.data.taxis.length) {
                        restalixo.value.data.taxis.forEach(function (item) {
                            arrcars = {};
                            arrcars["carname"] = item.car_model;
                            arrcars["originprice"] = item.regular_price;
                            arrcars["price_client"] = forexService.convertCurrency(item.regular_price, "EUR", userCurrency);
                            arrcars["discountprice_client"] = forexService.convertCurrency(item.discount_price, "EUR", userCurrency);
                            arrcars["packageId"] = item.id;
                            arrcars["image"] = item.image_url;
                            arrcars["freewaittime"] = item.included_waiting_time;
                            arrcars["maxluggage"] = item.luggage;
                            arrcars["maxpassengers"] = item.seats;
                            arrcars["discountprice"] = item.discount_price;
                            arrcars["vehicletype"] = item.vehicle_type;
                            arrcars["vendor"] = "Talixo";
                            arrcars["vehicleremarks"] = "Or Similar";
                            taxiresults.push(arrcars);
                        });
                    }
                    if (restalixo.value.data.limousines.length) {
                        restalixo.value.data.limousines.forEach(function (item) {
                            arrcars = {};
                            arrcars["carname"] = item.car_model;
                            arrcars["originprice"] = item.regular_price;
                            arrcars["price_client"] = forexService.convertCurrency(item.regular_price, "EUR", userCurrency);
                            arrcars["discountprice_client"] = forexService.convertCurrency(item.discount_price, "EUR", userCurrency);
                            arrcars["packageId"] = item.id;
                            arrcars["image"] = item.image_url;
                            arrcars["freewaittime"] = item.included_waiting_time;
                            arrcars["maxluggage"] = item.luggage;
                            arrcars["maxpassengers"] = item.seats;
                            arrcars["discountprice"] = item.discount_price;
                            arrcars["vehicletype"] = item.vehicle_type;
                            arrcars["vendor"] = "Talixo";
                            arrcars["vehicleremarks"] = "Or Similar";
                            taxiresults.push(arrcars);
                        });
                    }
                }
                //iwaytransfers supplier data
                if (resiway.status === "fulfilled") {
                    //console.log(resiway.value.data);
                    if (resiway.value.data.result.length) {
                        resiway.value.data.result.forEach(function (item) {
                            var imgsrc = "https://iwayex.com/images/cars/";
                            arrcars = {};
                            arrcars["carname"] = item.car_class.models[0];
                            arrcars["originprice"] = item.price;
                            arrcars["price_client"] = forexService.convertCurrency(item.price, "EUR", userCurrency);
                            arrcars["discountprice_client"] = forexService.convertCurrency(item.price, "EUR", userCurrency);
                            arrcars["packageId"] = item.price_uid;
                            arrcars["image"] = imgsrc + item.car_class.photo;
                            arrcars["freewaittime"] = item.allowable_time;
                            arrcars["maxluggage"] = "";
                            arrcars["maxpassengers"] = item.car_class.capacity;
                            arrcars["discountprice"] = item.price;
                            arrcars["vehicletype"] = item.vehicle_type;
                            arrcars["vendor"] = "iway Transfers";
                            arrcars["vehicleremarks"] = "Or Similar";
                            taxiresults.push(arrcars);
                        });
                    }
                }
        
                if (taxiresults.length) {
                    sortedresult = taxiresults.sort(function (a, b) {
                        return a.discountprice - b.discountprice;
                    });
                    res.status(200).send(sortedresult)
                }else{
                    res.status(200).send({})
                }
            });
        }

module.exports = {
    searchCars
}

this is the result sample i am getting.

{
carname: "Toyota Prius"
discountprice: 27.5
discountprice_client: {}
freewaittime: 45
image: "https://static.talixo.de/images/vehicles/economy.png"
maxluggage: 3
maxpassengers: 3
originprice: 27.5
packageId: "16021"
price_client: {}
vehicleremarks: "Or Similar"
vehicletype: "limo"
vendor: "Talixo"
}

here the problem is, i expect

discountprice_client: Converted Number, 

but i am getting blank object there as can be seen in above result sample. i have been using this in another function with async await, then it works fine. but in this case, i am not sure how to put async/await.

this is inside

forex.service.js

    const convertCurrency = async (amount, basecurrency, reqCurrency) => {
        if (basecurrency === reqCurrency) {
            let result = Math.round(amount) + ' ' + reqCurrency;
            return result;
        } else {
            const reqForexData = await getForexbyISO(reqCurrency);
            const baseForexData = await getForexbyISO(basecurrency);
            const amountInUSD = amount / baseForexData.forexRate;
            const amountInreqC = amountInUSD * reqForexData.forexRate;
            let result = Math.round(amountInreqC) + ' ' + reqCurrency;
            return result;
        }
    }

module.exports = {
    convertCurrency
}

You could do:

// notice the `async` before `function`
resiway.value.data.result.forEach(async function (item) {
  // ...
  arrcars = {};
  arrcars["price_client"] = await forexService.convertCurrency(item.price, "EUR", userCurrency);
  arrcars["discountprice_client"] = await forexService.convertCurrency(item.price, "EUR", userCurrency);
  // ...
});

But it can lead to unexpected behaviours

I would do this

// add missing `async`
return Promise.allSettled([talixoData, iwayData]).then(async ([restalixo, resiway]) => {
  // ...
  // await for all loop at once to avoid odd side effects
  await Promise.all(resiway.value.data.result.map(async function (item) {
    // ...
    arrcars = {};
    arrcars["price_client"] = await 
  forexService.convertCurrency(item.price, "EUR", userCurrency);
    arrcars["discountprice_client"] = await 
  forexService.convertCurrency(item.price, "EUR", userCurrency);
    // ...
  }));
  // ...
});

simplify your services

You are writing the Talixo and Iway services but using the result is difficult. Instead of returning the entire response, return the fields that matter to your consumer -

// services/talixo_service.js

async function findTalixoCars(query) {
  const result = await // ... perform request
  return result.value.data ?? [] // <- return relevant data
}

Notice we use return _____ ?? [] return _____ ?? [] to ensure that an array is always returned -

// services/iway_service.js

async function findiWayCars(query) {
  const result = await // ... perform request
  return result.value.data.result ?? [] // <- return relevant data
}

searchCars

With simplified services, we write a high-level implementation of searchCars . Instead of using Promise.allSettled we can use .catch(_ => []) on potential failures to guarantee we have an array result. This reduces the need for logical checks and code branches to make the code more declarative and less prone to errors -

async function searchCars(req, res) {
  const [talixo, iway] = await Promise.all([
    talixoService.findTalixoCars(req.body).catch(_ => []),
    iwayService.findiWayCars(req.body).catch(_ => [])
  ])

  const userCurrency = req.query.usercurrency ?? "INR"

  const taxis = [
    ...await Promise.all(talixo.taxis.map(item => fromTalixo(item, userCurrency))),
    ...await Promise.all(talixo.limousines.map(item => fromTalixo(item, userCurrency))),
    ...await Promise.all(iway.map(item => fromIway(item, userCurrency)))
  ]
  
  res.status(200).send(
    taxis.sort((a,b) => a.discountprice - b.discountprice)
  )
}

data mapping

The search function above depends on fromTalixo and fromIway . These mapping functions reduce code complexity and repitition and gives us a good conceptual model for how data gets mapped from the remote services to our local data -

async function fromTalixo(data, userCurrency) {
  return {
    carname: data.car_model,
    originprice: data.regular_price,
    price_client: await forexService.convertCurrency(data.regular_price, "EUR", userCurrency),
    discountprice_client: await forexService.convertCurrency(data.discount_price, "EUR", userCurrency),
    packageId: data.id,
    image: data.image_url,
    freewaittime: data.included_waiting_time,
    maxluggage: data.luggage,
    maxpassengers: data.seats,
    discountprice: data.discount_price,
    vehicletype: data.vehicle_type,
    vendor: "Talixo",
    vehicleremarks: "Or Similar",
  }
}
async function fromIway(data, userCurrency) {
  return {
    carname: data.car_class.models[0],
    originprice: data.price,
    price_client: await forexService.convertCurrency(data.price, "EUR", userCurrency),
    discountprice_client: await forexService.convertCurrency(data.price, "EUR", userCurrency),
    packageId: data.price_uid,
    image: `https://iwayex.com/images/cars/${data.car_class.photo}`,
    freewaittime: data.allowable_time,
    maxluggage: "",
    maxpassengers: data.car_class.capacity,
    discountprice: data.price,
    vehicletype: data.vehicle_type,
    vendor: "iway Transfers",
    vehicleremarks: "Or Similar",
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM