拥抱ES6——阿里云OSS推出JavaScript SDK
IssacWhiteh
9年前
<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>