拥抱ES6——阿里云OSS推出JavaScript SDK

IssacWhiteh 8年前
   <p>JavaScript作为当下最火的语言(之一),结合<a href="/misc/goto?guid=4959672529152005397">OSS</a>能够创建出非常丰富的跨前后端的应用。现在,OSS正式推出JavaScript SDK,使用OSS的 <strong>前后端</strong> 同学 <strong>都</strong> 可以方便地使用。</p>    <p>OSS JavaScript SDK基于<a href="/misc/goto?guid=4959672529241028357">ali-oss</a>开发,感谢<a href="/misc/goto?guid=4959672529319077552">@fengmk2</a>和<a href="/misc/goto?guid=4959672529397934936">@dead-horse</a>的指导,增加了许多功能并修复了一些bug,主要包括:</p>    <ul>     <li>支持在浏览器环境中使用</li>     <li>支持分片上传(multipart)</li>     <li>支持STS临时授权</li>     <li>修复若干bug</li>    </ul>    <p>详见:<a href="/misc/goto?guid=4959672529474539451">https://github.com/ali-sdk/ali-oss/blob/master/History.md#400–2016-01-22</a></p>    <h2>ES6</h2>    <p>首先,什么是ES6?</p>    <p><img alt="拥抱ES6——阿里云OSS推出JavaScript SDK" src="https://simg.open-open.com/show/0b699f6385d527020348742b449e89d2.png" width="532" height="291"></p>    <p>其实<a href="/misc/goto?guid=4958829314879541042">ES6</a>是最新版本的ECMAScript,也就是JavaScript标准。</p>    <blockquote>     <p>ECMAScript 6, also known as ECMAScript 2015, is the latest version of the ECMAScript standard. > ES6 is a significant update to the language…</p>    </blockquote>    <p>ES6包含了众多重要的更新,但是今天对我们最重要的就是<a href="/misc/goto?guid=4959672529585038563">Generator Function</a>,因为它可以让我们用同步的方式写异步代码:</p>    <pre>  <code class="language-javascript">var creds = yield  applySTSToken();  var client = new OSS(creds);  var result = yield client.list();  console.log(result);</code></pre>    <p>上面的代码包含了两个异步的操作,<code>applySTSToken</code>和<code>list</code>,如果没有generator,我们就需要在<code>applySTSToken</code>的callback中做<code>list</code>,然后在<code>list</code>的callback中做<code>log</code>,比如这样:</p>    <pre>  <code class="language-javascript">applySTSToken(function (creds) {    var client = new OSS(creds);    client.list(function (result) {      console.log(result);    });  });</code></pre>    <p>如果上面的代码看起来也“还可以”的话,那么当异步操作多起来之后,再考虑错误处理的场景,代码将会变得非常复杂。不得不说callback很锻炼大脑,但是有高科技为什么不利用呢?</p>    <p>这看起来不错,但是如何实现的呢?<a href="/misc/goto?guid=4959672529670279382">这篇文章</a>介绍了如何实现Promise(这真是个好名字)。最关键的地方就是<code>yield</code>让控制流跳转到其他代码执行,相应的事件(callback)发生时,通过<code>next</code>让控制流回到上次<code>yield</code>的地方继续执行,这样就达到了“异步非阻塞”的效果。</p>    <p>目前主流的Chrome/Firefox版本都已经支持ES6的大部分功能了。主流的Safari版本和移动端浏览器目前还不支持ES6,但是我们后面会讲到如何做兼容性转换。</p>    <h2>功能</h2>    <p>SDK目前支持OSS的绝大部分功能,包括上传/下载文件、分片上传、Bucket管理、文件管理等,常用的上传/下载也有多样的玩法:</p>    <ul>     <li>上传本地文件</li>     <li>上传Buffer内容</li>     <li>流式上传</li>     <li>分片上传</li>     <li>下载到本地文件</li>     <li>流式下载</li>    </ul>    <h3>安装</h3>    <pre>  <code class="language-javascript">npm install ali-oss co</code></pre>    <h3>上传文件</h3>    <p>使用<code>put</code>接口上传一个Object:</p>    <pre>  <code class="language-javascript">var OSS = require('ali-oss');  var co = require('co');  var fs = require('fs');    var client = new OSS({    accessKeyId: 'access key id',    accessKeySecret: 'access key secret',    region: 'oss-cn-hangzhou',    bucket: 'my-bucket',  });    co(function* () {    // put from local file    yield client.put('file', '/tmp/x');      // put from Buffer    yield client.put('buffer', new Buffer('hello world'));      // put from Stream    yield client.put('stream', fs.createReadStream('/tmp/x'));  }).catch(function (err) {    console.log(err);  });</code></pre>    <h3>下载文件</h3>    <p>使用<code>get</code>和<code>getStream</code>方法下载文件:</p>    <pre>  <code class="language-javascript">co(function* () {    // get as content    var result = yield client.get('object');    console.log(result.content);      // download as file    yield client.get('object', '/tmp/x');      // pipe to stream    yield client.get('object', fs.createWriteStream('/tmp/x'));      // get as stream    var result = yield client.getStream('object');    result.stream.pipe(fs.createWriteStream('/tmp/y'));  }).catch(function (err) {    console.log(err);  });</code></pre>    <h3>管理Bucket</h3>    <p>使用<code>putBucketLifecycle</code>等接口来设置Bucket的属性。注意,目前OSS不支持Bucket相关的跨域请求,所以在浏览器中不能使用Bucket的管理接口。</p>    <pre>  <code class="language-javascript">co(function* () {    var result = yield client.putBucketLifecycle('bucket', 'region', [      {        id: 'delete after one day',        prefix: 'logs/',        status: 'Enabled',        days: 1      },      {        prefix: 'logs2/',        status: 'Disabled',        date: '2022-10-11T00:00:00.000Z'      }    ]);  }).catch(function (err) {    console.log(err);  });</code></pre>    <h3>HTTP Headers</h3>    <p>SDK的每个方法都可以设置和获取HTTP Headers:</p>    <pre>  <code class="language-javascript">co(function* () {    // set headers    var result = yield client.put('object', '/tmp/x', {      headers: {        'content-type': 'application/javascript; charset=utf8'      }    });      // get headers    console.log(result.res.headers);  }).catch(function (err) {    console.log(err);  });</code></pre>    <h2>前端后端</h2>    <p><a href="/misc/goto?guid=4958830652694960670">Browserify</a>, <a href="/misc/goto?guid=4958877845976897237">Babel</a>等优秀工具的出现,使得我们能够在前后端共用一套代码。OSS JavaScript SDK基于Node.js开发,通过<a href="/misc/goto?guid=4958830652694960670">Browserify</a>和<a href="/misc/goto?guid=4958877845976897237">Babel</a>产生适用于浏览器的代码,使得OSS JavaScript SDK同时支持在浏览器中和Node.js环境中使用。</p>    <h3>在浏览器中使用</h3>    <p>用户在浏览器中使用SDK时,首先在<code><head></code>标签中包含如下<code><script></code>标签:</p>    <pre>  <code class="language-javascript"><script src="http://gosspublic.alicdn.com/aliyun-oss-sdk-4.1.4.min.js"></script></code></pre>    <p>就可以在代码中使用<code>OSS</code>对象:</p>    <pre>  <code class="language-javascript"><script type="text/javascript">    var client = new OSS({      region: '<oss region>',      accessKeyId: '<Your accessKeyId(STS)>',      accessKeySecret: '<Your accessKeySecret(STS)>',      stsToken: '<Your securityToken(STS)>',      bucket: '<Your bucket name>'    });      OSS.co(function* () {      var result = yield client.list({        'max-keys': 10      });      console.log(result);    }).catch(function (err) {      console.log(err);    });  </script></code></pre>    <p><strong>注意</strong>:上面的代码中用<code>OSS.co</code>代替<code>co</code>,同样的,如果用到了<code>Buffer</code>,也要使用<code>OSS.Buffer</code>代替。<a href="/misc/goto?guid=4959672529827553013">browser.js</a>中显示了SDK暴露给浏览器的全部对象。</p>    <p>我们提供一个<a href="/misc/goto?guid=4959672529901556452">demo</a>,使用OSS JavaScript SDK开发了一个浏览器应用,提供上传文件/上传文本/列出文件/下载文件 四个功能,效果如下:</p>    <p><img alt="拥抱ES6——阿里云OSS推出JavaScript SDK" src="https://simg.open-open.com/show/40ae95eb85210287b39ddd7ba7a4fc18.png" width="1350" height="871"></p>    <h3>Build SDK</h3>    <p>只需要在SDK的代码目录执行<code>npm run build-dist</code>命令,就可以生成用于浏览器的SDK lib:</p>    <pre>  <code class="language-javascript">git clone https://github.com/ali-sdk/ali-oss.git  cd ali-oss  npm install  npm run build-dist  # output  # dist/aliyun-oss-sdk.js  # dist/aliyun-oss-sdk.min.js</code></pre>    <h3>Build用户代码</h3>    <p>上述的例子中使用SDK的代码使用了<code>function*</code>和<code>yield</code>等ES6的特性,这在支持ES6的浏览器(主流版本的Chrome/Firefox)中可以直接运行,若要用于更多的浏览器,则需要使用<a href="/misc/goto?guid=4958830652694960670">Browserify</a>和<a href="/misc/goto?guid=4958877845976897237">Babel</a>进行兼容性转换:</p>    <pre>  <code class="language-javascript">npm install -g browserify  npm install babelify babel-preset-es2015  echo '{ "presets": ["es2015"] }' > .babelrc  browserify app.js -t babelify > app-babel.js</code></pre>    <p>转换后只需要在<code><script></code>标签中包含转换后的代码文件即可:</p>    <pre>  <code class="language-javascript"><script src="app-babel.js"></script></code></pre>    <h2>发布</h2>    <p>在SDK的开发过程中,每发布一个版本,我需要手动做以下几件事情:</p>    <ul>     <li>修改ChangeLog</li>     <li>修改package.json中的版本</li>     <li>生成版本的tag</li>     <li>生成dist/aliyun-oss-sdk.min.js</li>     <li>发布到npm</li>     <li><code>aliyun-oss-sdk.min.js</code>发布到cdn</li>    </ul>    <p>这么多步骤,不出错是几乎不可能的。所以我们使用<a href="/misc/goto?guid=4959672530015808607">git-extras</a>和<a href="/misc/goto?guid=4959672530090961641">git-pre-hooks</a>,让发布过程变成"All-in-One",具体参考<a href="/misc/goto?guid=4959672530171284345">package.json</a>。</p>    <p>首先确保在master分支,然后npm依赖都安装好了:</p>    <pre>  <code class="language-javascript">git checkout master  npm install</code></pre>    <p>发布过程:</p>    <pre>  <code class="language-javascript">vi package.json and change "version" to 4.2.0  git changelog -n -t 4.2.0  git release 4.2.0</code></pre>    <p>是不是如丝般顺滑?</p>    <ul>     <li>github(欢迎Star/Fork/PR): <a href="/misc/goto?guid=4959672529241028357">https://github.com/ali-sdk/ali-oss</a></li>     <li>API文档:<a href="/misc/goto?guid=4959672530258895167">https://github.com/ali-sdk/ali-oss#summary</a></li>     <li>SDK文档:<a href="/misc/goto?guid=4959672530337103543">https://help.aliyun.com/document_detail/oss/sdk/javascript-sdk/install.html</a></li>    </ul>    <p>来自:http://cnodejs.org/topic/56ab1c0526d02fc6626bb383</p>