使用fetch代替ajax发送数据实践(node+webpack)--whatwg-fetch

3 篇文章 0 订阅
3 篇文章 0 订阅
  1. 安装whatwg-fetch(和ajax一样,新的获取数据方式,支持promise语法)获取数据。安装方法:
npm install whatwg-fetch --save; 
or
bower install fetch.
  1. 导入依赖。注意这里的导入只能使用**import 'whatwg-fetch';**接着是发送xhr请求的代码,我们将其封装成一个方法,如下
function myFetch(Url){
    fetch(Url)
        .then(function(response) {
            console.log(response);
            return response.text();
        })
        .then((data) => {
            console.log(data);
        }).catch(e=>{console.log(e);})
}

解释下:以上方法接收一个url请求地址,请求后返回一个response文本。打印出来如下:
response
可见这个对象有一些自己的方法如OK、status等还有些原型方法如text()等。这里我们将text()的内容返回。
3. 接着将其暴露出去,给其他js文件引用。module.exports = myFetch;
4. 定义另一个index.js文件,代码如下:

import myFetch from './index6'
myFetch("http://localhost:3000/users");

解释:从之前的文件导出myfetch方法并调用。其中from后面跟的是之前的js所在相对路径。
这个方法访问的是监听在3000端口的一个服务端程序。这里我们直接使用node搭建一个建议的web服务器。
5. 搭建过程如下:
随便拷贝一个node服务器最小化模版

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});
// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  // render the error page
  res.status(err.status || 500);
  res.render('error');
});
module.exports = app;

以上代码主要设计express的相关知识,大家可看这篇文章
最关键的部分:app.use('/', index);app.use('/users', users);这里就定义了,当访问的路径为hostname+/的时候交给index处理,当然访问hostname+/users的时候交给users处理。这里的我们只关注后一个路径。交给users处理也就是交给users.js处理。
我们看下users.js内容:

var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});
module.exports = router;

解释:引入express的路由模块,并设置当请求的子域名是/的时候就response一个文本。这里的/和app.use(‘/users’, users);一起构成了一个完整的请求。例如,如果这里写/a,则这个请求为/users/a的时候才会触发这个路由规则。
6. 之前只是定义了路由规则,接下来引用这个app规则并启动,代码如下:

#!/usr/bin/env node
var app = require('../app');
var debug = require('debug')('react-demos:server');
var http = require('http');
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
function normalizePort(val) {
  var port = parseInt(val, 10);
  if (isNaN(port)) {
    // named pipe
    return val;
  }
  if (port >= 0) {
    // port number
    return port;
  }
  return false;
}
function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }
  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;
  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}
function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

这里引入了app,并且设置监听在3000端口,也就是我们需要提供http://localhost:3000/users数据的端口。
7. 接下来启动node,将上面的代码放到start.js中然后输入node start.js启动node
8. 然后,写一个html并引入刚刚的js文件,我们使用webpack打包。html文件内容如下:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
</head>
<body>
<div id="example"></div>
<script src="./bundle.js"></script>
</body>
</html>

这里引用的是bundle.js这是打包后的js文件,可以自定义。
9. 我们看打包的配置文件,配置如下:

module.exports = {
    entry: ['./index.js'],
    output: {
        filename: 'bundle.js',
        path: './'
    }
};

解释:将绝对路径下的index.js打包成当前路径下的bundle.js然后html就可以引用了。
10. 打包命令(最好使用本项目内的webpack来打包并指定配置文件)

 ../../node_modules/.bin/webpack --config webpack.config.js
  1. 访问,点击webstorm上的浏览器按钮,直接访问。此时会报错,已拦截跨源请求:同源策略禁止读取位于 http://localhost:3000/users 的远程资源。(原因:CORS 头缺少 ‘Access-Control-Allow-Origin’)。这是因为,访问的网址和fetch请求资源的网址跨域了,跨域可见这篇文章
  2. 解决跨域,node服务器端配置下允许访问的字段。代码如下:
app.all('*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "http://localhost:63343");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  res.header("Access-Control-Allow-Credentials", "true");
  res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
  res.header("X-Powered-By",' 3.2.1');
  res.header("Content-Type", "application/json;charset=utf-8");
  next();
});

原理:我们看下/users访问的请求头请求头
可见origin字段(用来说明,本次请求来自哪个源(协议 + 域名 + 端口),来源于localhost:63343也就是webstorm自带的web服务器的端口。Host表示发起当前请求的域名 + 端口。可见这两个不一致,所以跨域产生。我们要做的就是,告诉服务器,这个域名是可以被接收的,也就是允许localhost:63343跨域请求,所以才会有以上的配置。
接着看下响应头响应头
可以看到,node服务器返回了我们刚刚配置的响应Access-Control-Allow-Origin,浏览器接收到这个响应,就会正常处理,否则进入error处理。


最后正常的结果就是,控制台打印了如下内容:

Response { type: "cors", url: "http://localhost:3000/users", redirected: false, status: 200, ok: true, statusText: "OK", headers: Headers, bodyUsed: false }  bundle.js:7855:10


----------


respond with a resource

以上就是,整个从安装fetch到使用fetch到使用node搭建服务器到解决fetch跨域问题的流程,下一篇,我们继续研究fetch-jsonp,敬请期待。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值