Webpack将父范围显示为未定义

时间:2016-02-15 21:15:14

标签: javascript webpack babeljs

编辑:我刚刚完成了切换回浏览器的过程,并遇到了同样的问题。所以不再是webpack问题了。仍然需要帮助

我正在从broswerify切换到webpack。我为我的ajax调用创建了一个抽象。在该文件中,我有一些私有变量,我用它来设置URL和超时等。由于某种原因,它显示这些变量(和整个'闭包')未定义,导致一些奇怪的错误。这段代码与browserify完美配合。

这是我的webpack.config.js

const webpack = require('webpack');
const path = require('path');

module.exports = {
	devtool: 'source-map',
	entry: path.resolve(__dirname, 'src', 'client', 'index.js'),
	output: {
		path: path.resolve(__dirname, 'public'),
		publicPath: 'localhost:3002',
		filename: 'bundle.js',
	},
	module: {
		loaders: [
			{
				test: /\.js$/,
				loader: 'babel',
				exclude: /node_modules/,
			},
			{
				test: /\.(png|jpg)$/,
				loader: 'url-loader',
			},
		],
	},
	plugins: [
		new webpack.DefinePlugin({
			__API_URL__: JSON.stringify('http://localhost:3002/api'),
		}),
	],
};

这是我的api包装api.js

import request from 'superagent';

import store from './store';
import { system, account } from '../core/actions';

const API_URL = __API_URL__;
const TIMEOUT = 10000;
const _pendingRequests = {};

function getJwt() {
	/**
	 * This retrieves the JSON Web Token from local or session storage
	 * We simply try both so that we don't have to subscribe to the store
	 * and make sure some flag is constantly updated. The reducer that handles
	 * the successful login will place the token in the proper place.
	 */
	let token = localStorage.getItem('JWT_TOKEN');
	if (token) {
		return 'Bearer ' + token;
	}

	token = sessionStorage.getItem('JWT_TOKEN');
	if (token) {
		return 'Bearer ' + token;
	}

	return null;
}

function addRequest(key, pendingRequest) {
	_pendingRequests[key] = pendingRequest;
}

function abortPendingRequests(key) {
	if (_pendingRequests.hasOwnProperty(key)) {
		_pendingRequests[key]._callback = () => {
		};
		_pendingRequests[key].abort();
		_pendingRequests[key] = null;
	}
}

function digest(resolve, reject) {
	return function consume(err, res) {
		if (err && err.timeout === TIMEOUT) {
			return store.dispatch(system.apiTimeout());

		} else if (res.status === 401) {
			return store.dispatch(account.logout());
		} else if (!res.ok) {
			return reject(res);
		} else {
			if (err) {
				return reject(err);
			} else {
				return resolve(res.body);
			}
		}
	};
}

export function get(actionType, resource) {
	// abortPendingRequests(actionType);
	return new Promise((resolve, reject) => {
		const jwt = getJwt();

		const url = `${API_URL}${resource}`;

		const requested = request
			.get(url)
			.timeout(TIMEOUT);

		if (jwt) {
			requested.set('Authorization', jwt);
		}

		// addRequest(actionType, requested);

		requested.end(digest(resolve, reject));
	});
}

export function post(actionType, resource, data) {
	// abortPendingRequests(actionType);
	return new Promise((resolve, reject) => {
		const jwt = getJwt();

		const url = `${API_URL}${resource}`;

		const requested = request
			.post(url)
			.timeout(TIMEOUT);

		if (jwt) {
			requested.set('Authorization', jwt);
		}

		if (data) {
			requested.send(data);
		}

		// addRequest(actionType, requested);

		requested.end(digest(resolve, reject));
	});
}

export function put(actionType, resource, data) {
	// abortPendingRequests(actionType);
	return new Promise((resolve, reject) => {
		const jwt = getJwt();

		const url = `${API_URL}${resource}`;

		const requested = request
			.put(url)
			.timeout(TIMEOUT);

		if (jwt) {
			requested.set('Authorization', jwt);
		}

		if (data) {
			requested.send(data);
		}

		requested.end(digest(resolve, reject));
	});
}

export function del(actionType, resource) {
	// abortPendingRequests(actionType);
	return new Promise((resolve, reject) => {
		const jwt = getJwt();

		const url = `${API_URL}${resource}`;

		const requested = request
			.del(url)
			.timeout(TIMEOUT);

		if (jwt) {
			requested.set('Authorization', jwt);
		}

		// addRequest(actionType, requested);

		requested.end(digest(resolve, reject));
	});
}

有一些奇怪的评论是尝试调试问题的结果。但基本上,如果我在const _pendingRequests = {};设置断点,则会显示API_URLTIMEOUT正确设置。但是,如果我在const url =中的; $ {API_URL} $ {resource} export function get设置了断点,则会将其显示为未定义,因为我将使用屏幕截图显示。

Parent scope

Child Scope

我只是注意到,在打破父范围之前,它正在打破子范围。我猜这与它有关,但我不知道如何改变这种行为。我在节点工作,所以我写了这个,就像我会为服务器写它。

这是我导入api.js

的文件

import * as api from '../../core/api';
import { endpoints } from '../../constants';

export const FETCH_LOOKUPS = 'FETCH_LOOKUPS';
export const FETCH_LOOKUPS_SUCCESS = 'FETCH_LOOKUPS_SUCCESS';

export function fetchLookupsSuccess(lookups) {
	return {
		type: FETCH_LOOKUPS_SUCCESS,
		lookups,
	};
}

export function asyncFetchLookups() {
	return dispatch => {
		return api.get(FETCH_LOOKUPS, endpoints.LOOKUP)
			.then(lookups => dispatch(fetchLookupsSuccess(lookups)));
	};
}

export const FETCH_LANG = 'FETCH_LANG';
export const FETCH_LANG_SUCCESS = 'FETCH_LANG_SUCCESS';

export function fetchLangSuccess(language) {
	return {
		type: FETCH_LANG_SUCCESS,
		language,
	};
}

export function asyncFetchLang() {
	return dispatch => {
		return api.get(FETCH_LANG, endpoints.LANGUAGE)
			.then(language => dispatch(fetchLangSuccess(language)));
	};
}

开始深入研究已编译的代码并找到了这个

function(module, exports, __webpack_require__) {

	'use strict';
	
	Object.defineProperty(exports, "__esModule", {
		value: true
	});
	exports.TIMEOUT = exports.API_URL = undefined;
	exports.get = get;
	exports.post = post;
	exports.put = put;
	exports.del = del;
	
	var _superagent = __webpack_require__(427);
	
	var _superagent2 = _interopRequireDefault(_superagent);
	
	var _store = __webpack_require__(430);
	
	var _store2 = _interopRequireDefault(_store);
	
	var _actions = __webpack_require__(444);
	
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	
	var API_URL = exports.API_URL = ("http://localhost:3002/api"); /**
	                                              * This file serves as a wrapper for any ajax requests that need to be made
	                                              * - contains a generic call for PUT, POST, GET and DELETE request
	                                              * - always attempts to append a JSON Web Token if present
	                                              * - keeps track of all pending requests and aborts identical requests
	                                              */
	
	var TIMEOUT = exports.TIMEOUT = 10000;

正如您所看到的,它最初将TIMEOUT和API_URL设置为未定义。然后,它会导出getpost等,然后设置TIMEOUT和API_URL,但这是在导出的get已被访问之后。不确定为什么它将它们设置为未定义或如何解决此问题。

2 个答案:

答案 0 :(得分:0)

根据您的需要(可能是导入),{% include 'modal_form.html' with modal_form_id="new-category" modal_form_title="Create a New Category" modal_form_method="POST" modal_form_action="/home/" form=category_form %} 函数babel可以首先转换get函数并将其交给节点的require,然后将其删除。

然后你还没有编译get。这看起来像一个边缘情况。

使用API_URL而不是使用ES6 export,而是使用module.exports并使用节点require导入它以解除此类错误。

如果此方法有效,请尝试使用import而不是require(并绕过export而不是使用module.exports)来缩小错误。

注意:这是一个提示/解决方法,而不是解决方案。您可以提供您提出要求的文件,这可能对其他人有用。

答案 1 :(得分:0)

问题与javascript完成解析之前调用的函数有关。 (仍然不确定原因)我发现的解决方法是将我的初始化函数附加到窗口对象,并在我的HTML正文的IIFE中调用它。