【发布时间】:2018-08-03 19:19:11
【问题描述】:
我有一些使用 async/await 的代码给我带来了一个非常奇怪的问题:我用 await 语句设置的变量在表达式之后抛出了一个未定义的引用 rrror!代码如下:
export const fetchPrices = async ({ commit }, ticker) => {
const key= "*********";
const url =
`http://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=${ticker}&interval=1min&apikey=${key}`
commit(FETCH_PRICES_REQUEST, { ticker })
try {
let response = await fetch(url);
let priceData = await response.json();
}
catch (e) {
console.error(e);
}
commit(FETCH_PRICES_SUCCESS, priceData)
};
运行时,函数的最后一行会抛出几个错误:
ReferenceError: 响应未定义
和
Uncaught (in promise) ReferenceError: priceData is not defined
这对我来说没有多大意义,因为我的理解是 await 的整个用法是对变量的赋值应该由下一行代码完成。
我实际上已经解决了这个问题,这与我声明变量的位置有关。当我通过将以下行放在函数顶部将声明移到 try/catch 块之外时,它起作用了:
let response, priceData;
出于好奇,我在 Babel 中查看了转换后的代码。文件顶部的声明如下所示:
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
var fetchPrices = exports.fetchPrices = function () {
var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(_ref2, ticker) {
var commit = _ref2.commit;
var response, priceData, key, url;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
response = void 0, priceData = void 0;
key = "EH6GPZQ5X8EUM3MC";
url = "http://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=" + ticker + "&interval=1min&apikey=" + key;
commit(FETCH_PRICES_REQUEST, { ticker: ticker });
_context.prev = 4;
_context.next = 7;
return fetch(url);
case 7:
response = _context.sent;
_context.next = 10;
return response.json();
case 10:
priceData = _context.sent;
_context.next = 16;
break;
case 13:
_context.prev = 13;
_context.t0 = _context["catch"](4);
console.error(_context.t0);
case 16:
commit(FETCH_PRICES_SUCCESS, priceData);
case 17:
case "end":
return _context.stop();
}
}
}, _callee, undefined, [[4, 13]]);
}));
return function fetchPrices(_x, _x2) {
return _ref.apply(this, arguments);
};
}();
关键区别在于第一个案例顶部的行 (case 0):
response = void 0, priceData = void 0;
似乎发生的情况是,如果您不在函数顶部声明变量,那么案例 7 和案例 10 在尝试分配给这些变量时会失败。
我的问题是这是否是 async/await 编译代码的问题,或者我尝试在 try/catch 块中声明变量是否根本错误。
【问题讨论】:
-
let是块作用域。当您在try{}中声明这些变量时,它们的作用域是由大括号创建的块。 -
用 let/const 定义的变量是阻塞范围
-
@Akrion
response是,但在 try/catch 之外,操作尝试使用priceData,其范围仍为try。这个场景是一个完美的例子,将这些请求添加到数组并使用promise.all解析和运行`commit(FETCH_PRICES_SUCCESS, priceData)` 函数,imo。 -
@MarkMeyer,我更改了几次变量名,忘记更新我在问题中的评论。我马上更新。
-
@fraxture,这个问题真的是一个范围问题,但是
promise.all会在你可能有多个连续等待时减轻痛苦。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…