Мне нужна ваша помощь, потому что я получил typeError, упомянутый в вопросе, и я не уверен, почему. У меня есть объект (который возвращается из запроса-обещания), который выглядит следующим образом:

{
                   "statusCode": 200,
                   "body": {
                      "BTC_USD": {
                         "buy_price": "4258",
                         "sell_price": "4265",
                         "last_trade": "4265",
                         "high": "4360",
                         "low": "4200",
                         "avg": "4260.2077946",
                         "vol": "219.32404491",
                         "vol_curr": "933982.49730504",
                         "updated": 1503767188
                      },
                      "BTC_EUR": {
                         "buy_price": "3640.1001",
                         "sell_price": "3650",
                         "last_trade": "3644.8",
                         "high": "3801.999999",
                         "low": "3622.000006",
                         "avg": "3685.0414084",
                         "vol": "94.48595035",
                         "vol_curr": "347993.56447153",
                         "updated": 1503767128
                      },
                      "BTC_RUB": {
                         "buy_price": "243511",
                         "sell_price": "244340",
                         "last_trade": "243511.49870226",
                         "high": "248786.99",
                         "low": "239630",
                         "avg": "243430.47675799",
                         "vol": "140.12303781",
                         "vol_curr": "34185015.26771479",
                         "updated": 1503767190
                      },
                      "BTC_UAH": {
                         "buy_price": "107000",
                         "sell_price": "107790",
                         "last_trade": "107790",
                         "high": "109900",
                         "low": "105354",
                         "avg": "108167.30195869",
                         "vol": "34.94251977",
                         "vol_curr": "3770330.73968614",
                         "updated": 1503767167
                      },
                      "DASH_BTC": {
                         "buy_price": "0.08528559",
                         "sell_price": "0.08644069",
                         "last_trade": "0.086196",
                         "high": "0.093364",
                         "low": "0.07043",
                         "avg": "0.0803689",
                         "vol": "1595.2753788",
                         "vol_curr": "123.76291968",
                         "updated": 1503767189
                      },
                   },
                   "request": {
                      "uri": {
                         "protocol": "https:",
                         "slashes": true,
                         "auth": null,
                         "host": "api.exmo.com",
                         "port": 443,
                         "hostname": "api.exmo.com",
                         "hash": null,
                         "search": null,
                         "query": null,
                         "pathname": "/v1/ticker/",
                         "path": "/v1/ticker/",
                         "href": "https://api.exmo.com/v1/ticker/"
                      },
                      "method": "GET",
                      "headers": {
                         "accept": "application/json"
                      }
                  }
                }

Как вы можете видеть, body имеет несколько объектов, и моя цель - переупорядочить информацию в новом макете для каждого body.keys:

Object.keys(res.body).forEach((k) => {
          result= {
            mk: 'exmo',
            name: k,
            a: res.body[k].sell_price,
            b: res.body[k].buy_price,
            c: res.body[k].last_trade,
            v: res.body[k].vol,
            t: res.body[k].vol_curr,
            l: res.body[k].low,
            h: res.body[k].high,
            sn: res.body[k].updated,
          }
        });
        return result;

Но по какой-то причине это не работает ... Я чувствую, что не правильно использую Promise.all?

Вот мой полный код для тестирования (он воспроизводит ошибку):

function exmo() {
  Promise.all(
    function () {
        var result = {};
        var res = {
                   "statusCode": 200,
                   "body": {
                      "BTC_USD": {
                         "buy_price": "4258",
                         "sell_price": "4265",
                         "last_trade": "4265",
                         "high": "4360",
                         "low": "4200",
                         "avg": "4260.2077946",
                         "vol": "219.32404491",
                         "vol_curr": "933982.49730504",
                         "updated": 1503767188
                      },
                      "BTC_EUR": {
                         "buy_price": "3640.1001",
                         "sell_price": "3650",
                         "last_trade": "3644.8",
                         "high": "3801.999999",
                         "low": "3622.000006",
                         "avg": "3685.0414084",
                         "vol": "94.48595035",
                         "vol_curr": "347993.56447153",
                         "updated": 1503767128
                      },
                      "BTC_RUB": {
                         "buy_price": "243511",
                         "sell_price": "244340",
                         "last_trade": "243511.49870226",
                         "high": "248786.99",
                         "low": "239630",
                         "avg": "243430.47675799",
                         "vol": "140.12303781",
                         "vol_curr": "34185015.26771479",
                         "updated": 1503767190
                      },
                      "BTC_UAH": {
                         "buy_price": "107000",
                         "sell_price": "107790",
                         "last_trade": "107790",
                         "high": "109900",
                         "low": "105354",
                         "avg": "108167.30195869",
                         "vol": "34.94251977",
                         "vol_curr": "3770330.73968614",
                         "updated": 1503767167
                      },
                      "DASH_BTC": {
                         "buy_price": "0.08528559",
                         "sell_price": "0.08644069",
                         "last_trade": "0.086196",
                         "high": "0.093364",
                         "low": "0.07043",
                         "avg": "0.0803689",
                         "vol": "1595.2753788",
                         "vol_curr": "123.76291968",
                         "updated": 1503767189
                      },
                   },
                   "request": {
                      "uri": {
                         "protocol": "https:",
                         "slashes": true,
                         "auth": null,
                         "host": "api.exmo.com",
                         "port": 443,
                         "hostname": "api.exmo.com",
                         "hash": null,
                         "search": null,
                         "query": null,
                         "pathname": "/v1/ticker/",
                         "path": "/v1/ticker/",
                         "href": "https://api.exmo.com/v1/ticker/"
                      },
                      "method": "GET",
                      "headers": {
                         "accept": "application/json"
                      }
                  }
                }
        Object.keys(res.body).forEach((k) => {
          result= {
            mk: 'exmo',
            name: k,
            a: res.body[k].sell_price,
            b: res.body[k].buy_price,
            c: res.body[k].last_trade,
            v: res.body[k].vol,
            t: res.body[k].vol_curr,
            l: res.body[k].low,
            h: res.body[k].high,
            sn: res.body[k].updated,
          }
        });
        return result;
    }).then((data) => {
    console.log(JSON.stringify(data, null, 3));
  })
};

exmo();

Заранее всем спасибо за помощь!

***** РЕДАКТИРОВАТЬ *****: [Попытка уточнить] Моя цель состояла в том, чтобы получить один объект за итерацию forEach. В конечном итоге каждый из этих объектов попадет в базу данных Монго. Я неправильно использую Promise.all (потому что ему нужен массив обещаний), но искал похожее решение.

0
Ardzii 26 Авг 2017 в 20:57

3 ответа

Лучший ответ

Ваш вопрос немного усложняется из-за того, что ваш код объединен воедино, поэтому здесь я разделил его.

Эта функция имитирует ответ сервера в качестве примера , чтобы показать вам, как можно управлять обещанием.

function getData() {
  return new Promise((resolve, reject) => {

    // Parse the returned data
    resolve(JSON.parse(res));
  });
}

Тогда вам нужно преобразовать свои данные. Здесь вы можете использовать map для итерации по объекту вместо forEach:

function mapData(obj) {
  return Object.keys(obj.body).map((k) => {
    return {
      mk: 'exmo',
      name: k,
      a: res.body[k].sell_price,
      b: res.body[k].buy_price,
      c: res.body[k].last_trade,
      v: res.body[k].vol,
      t: res.body[k].vol_curr,
      l: res.body[k].low,
      h: res.body[k].high,
      sn: res.body[k].updated
    }
  });
}

Затем вы можете просто вызвать getData, mapData, а затем вывести результат. Вы не хотите Promise.all здесь, потому что этот метод принимает только массив обещаний.

getData()
  .then(mapData)
  .then(data => console.log(JSON.stringify(data, null, 3)));

DEMO . в getData).

2
Andy 26 Авг 2017 в 18:44

Как вы можете видеть, вы снова и снова назначаете result в нормальном цикле forEach(), return в конце может вернуть только информацию о последнем ключе в {{X3} } .
Что вам нужно сделать, это поместить все значения с одним и тем же ключом в массив (возможно?). Или проще: перенести всю таблицу.
Следовательно, сначала нужно объявить кучу Array:

// init
let result = { };
let keys = ['buy_price', 'sell_price', /* etc. */];
keys.forEach(k => result[k] = []);

// gathering informations
Object.keys(res.body).forEach(name =>
    Object.keys(res.body[name]).forEach(k => result[k].push(res.body[name][k]))
);

Теперь вы можете легко получить информацию по индексу result.

Если вы хотите проиндексировать их по оригинальным именам, вы можете сначала инициализировать result как группу Object, а затем использовать name вместо непосредственного push() в внутренний forEach().

Object.keys(res.body[name]).forEach(k => result[k][name] = res.body[name][k])

Что имеет больше смысла в «транспонировании» всей таблицы.

1
Nianyi Wang 26 Авг 2017 в 18:12

Promise.all (итерируемый) принимает итеративный объект, такой как Array или String.

Я изменил ваш код, он дает вывод. Примечание: - Вашу логику кода я не изменил, это дало результат как ваша логика.

function exmo() {
  var data = (function () {
        var result = {};
        var res = {
                   "statusCode": 200,
                   "body": {
                      "BTC_USD": {
                         "buy_price": "4258",
                         "sell_price": "4265",
                         "last_trade": "4265",
                         "high": "4360",
                         "low": "4200",
                         "avg": "4260.2077946",
                         "vol": "219.32404491",
                         "vol_curr": "933982.49730504",
                         "updated": 1503767188
                      },
                      "BTC_EUR": {
                         "buy_price": "3640.1001",
                         "sell_price": "3650",
                         "last_trade": "3644.8",
                         "high": "3801.999999",
                         "low": "3622.000006",
                         "avg": "3685.0414084",
                         "vol": "94.48595035",
                         "vol_curr": "347993.56447153",
                         "updated": 1503767128
                      },
                      "BTC_RUB": {
                         "buy_price": "243511",
                         "sell_price": "244340",
                         "last_trade": "243511.49870226",
                         "high": "248786.99",
                         "low": "239630",
                         "avg": "243430.47675799",
                         "vol": "140.12303781",
                         "vol_curr": "34185015.26771479",
                         "updated": 1503767190
                      },
                      "BTC_UAH": {
                         "buy_price": "107000",
                         "sell_price": "107790",
                         "last_trade": "107790",
                         "high": "109900",
                         "low": "105354",
                         "avg": "108167.30195869",
                         "vol": "34.94251977",
                         "vol_curr": "3770330.73968614",
                         "updated": 1503767167
                      },
                      "DASH_BTC": {
                         "buy_price": "0.08528559",
                         "sell_price": "0.08644069",
                         "last_trade": "0.086196",
                         "high": "0.093364",
                         "low": "0.07043",
                         "avg": "0.0803689",
                         "vol": "1595.2753788",
                         "vol_curr": "123.76291968",
                         "updated": 1503767189
                      },
                   },
                   "request": {
                      "uri": {
                         "protocol": "https:",
                         "slashes": true,
                         "auth": null,
                         "host": "api.exmo.com",
                         "port": 443,
                         "hostname": "api.exmo.com",
                         "hash": null,
                         "search": null,
                         "query": null,
                         "pathname": "/v1/ticker/",
                         "path": "/v1/ticker/",
                         "href": "https://api.exmo.com/v1/ticker/"
                      },
                      "method": "GET",
                      "headers": {
                         "accept": "application/json"
                      }
                  }
                }
        Object.keys(res.body).forEach((k) => {
          result= {
            mk: 'exmo',
            name: k,
            a: res.body[k].sell_price,
            b: res.body[k].buy_price,
            c: res.body[k].last_trade,
            v: res.body[k].vol,
            t: res.body[k].vol_curr,
            l: res.body[k].low,
            h: res.body[k].high,
            sn: res.body[k].updated,
          }
        });
        return result;
    });
    
    Promise.all([data()]).then((data) => {
    console.log(JSON.stringify(data, null, 3));
  })
};

exmo();

<!-- begin snippet: js hide: false console: true babel: false -->
1
Srinath reddy 26 Авг 2017 в 18:36