倾听用户:OSS JavaScript SDK支持callback方式
发布于 1 年前 作者 rockuw 5416 次浏览 最后一次编辑是 8 个月前 来自 分享

阿里云OSS SDK for JavaScript刚推出时,为了解救Callback Hell,我们积极拥抱ES6。经过一段时间的使用,收到了很多好评(虽然大部分是给ES的),同时也收到了不少抱怨,coyield对于很多用户来说还是有不低的使用门槛。现在,对callback情有独钟的朋友们,也可以愉快地使用OSS js sdk了:

安装

# >= 4.3.0
npm install ali-oss

使用:

var OSS = require('ali-oss').Wrapper;

var client = new OSS({
  region: 'oss-cn-hangzhou',
  accessKeyId: '<access-key-id>',
  accessKeySecret: '<access-key-secret>',
  bucket: '<bucket-name>'
});

client.list().then(function (result) {
  console.log(result.objects);
}).catch(function (err) {
  console.error(err);
});

使用Wrapper构造出来的OSS对象拥有原来的所有接口,只是把原来的generator function换成了普通的函数,并且返回一个Promise,通过.then()处理异步结果,通过.catch()处理错误。当然原来的使用方式依然支持。

Promise的使用与Callback接近,但是却可以更加灵活。例如对于多层嵌套的callback,可以使用Promise chaining的方式让代码更直观:

// 上传一个文件,成功后下载这个文件
client.put('object', '/tmp/file').then(function (val) {
  console.log(val.res);
  return client.get('object');
}).then(function (val) {
  console.log(val.res);
  console.log(val.content.toString());
});

浏览器使用也更方便了:

<script src="http://gosspublic.alicdn.com/aliyun-oss-sdk.min.js"></script>
<script type="text/javascript">
  var client = new OSS.Wrapper({
    region: 'oss-cn-hangzhou',
    accessKeyId: '<access-key-id>',
    accessKeySecret: '<access-key-secret>',
    bucket: '<bucket-name>'
  });
  
  client.list().then(function (result) {
    console.log(result.objects);
  });
</script>

一个完整的例子可以参考:https://github.com/rockuw/oss-in-browser

除此之外,SDK还有众多的优化,欢迎试用:

  • 简化浏览器版本体积,从1.1MB下降到360KB。#94
  • 支持断点续传。#80
  • 更多bug fix及优化见:changelog

项目地址(欢迎fork/star/pr):https://github.com/ali-sdk/ali-oss

28 回复

我想问一句,这是当大家分不清 promise 和callback吗?

nodejs库都是直接callback,你整个promise到底是聪明还是智商不够?

感觉这个sdk要成为众矢之的了~

@alsotang 求教区别是什么?

client.put('object', '/tmp/x', function (data) { });

client.put('object', '/tmp/x').then(function (data) {});

@gzhangzy Promise相对于callback,有哪一点你认为接受不了呢?

@rockuw 我就想直接callback,要加Promise我自己加。现在是我不想要确去不掉。那个Promise有那么好吗?nodejs那点性能优势都被干掉了。而且实际编程中的问题也解决不了。

要考虑的模型:

if xxx then xxx;
else xxx;
if yyy then yyy;
else yyy;

Promise其实是假设else是错误处理,而实际更多的情况是分支。同步代码写着没看谁说不舒服,到了异步代码,Promise怎么就能假设then then then …下去呢?我就不能有else分支吗?

我觉得代码要一层层封装。比如,先写个 write ,然后再写个 fwrite,然后再重载个运算符 >> 。 你别把次序倒过来,先提交个 >>;不行再来个fwrite;最后你还得给了write。

@gzhangzy 你提到了两个问题:

  1. Promise导致性能比callback差,这个我没有足够的判断,大家可以讨论讨论
  2. Promise的thenif thenthen不是同一个东西啊,你能不能举个具体的例子?把callback的写法和Promise的写法都贴出来,对比一下

@gzhangzy ES6和ES5的关系不是fwrite和write的关系,babel干的事情也是类似的。

@rockuw https://cnodejs.org/topic/570cfd57d3220b7e4e304641 这篇里我说了循环异步编程的问题,你可以看看。至于分支异步编程的问题更简单了,看完你再决定是否讨论。

@gzhangzy 看完了,讨论吧。

我是渣渣,说错了不要在意,啦啦啦。


可不可以这样?

// callback
client.put('object', '/tmp/file').exec(function (err, callback) {
	// balabala
});
// Promise
client.put('object', '/tmp/file').then(function (result) {
	// balabala
});

传统语言中主要过程控制方法有三种: 1)if语句及switch语句 2)循环语句和goto语句 3)函数或过程(js在这一点上变了)

编程语言都是按照机器执行次序编写的,而程序猿希望按照自己的逻辑组织程序。这一点在 js这门语言上产生了重大冲突。推荐一种编程书写方法,例如promise,应该从: 1)promise如何编写if或switch分支; 2)promise如何编写循环或goto逻辑; 3)函数或过程调用中如何用callback代替return; 都说到了,我说promise牛。说不到就不能说是大法。

@gzhangzy

  1. if/switch/while都跟是Promise还是callback无关,该怎么写还怎么写
  2. 我理解Promise和callback是等价的,callback能干的promise也能干,反之亦然
  3. Promise是composable的,这是它比callback更好的地方

It is fair to say promises are just syntactic sugar. Everything you can do with promises you can do with callbacks. In fact, most promise implementations provide ways of converting between the two whenever you want. The deep reason why promises are often better is that they’re more composeable, …

http://programmers.stackexchange.com/questions/302455/is-there-really-a-fundamental-difference-between-callbacks-and-promises

@rockuw Promise 不是语法糖,贴一段我读Promise的体会。

Promise代码体会

带有一个函数参数的函数 f1(f2) ,可以先造一个f2’,这样就可以把它执行了 f1(f2’)。

这个f2’的功能要这样实现:当执行到f2’时,f2’要检查真实的f2是否已经准备好了?如果准备好了,就调用真实的f2;否则,要把调用f2的参数都记下来,等f2准备好时调用。

这样就不需要要求调用f1时,f2必须准备好了。但额外要提供一个提交f2的方法。

以上就是Promise揭示的异步编程技巧。在Promise中,factory是f1;resolve和reject是f2’;then和catch是提交f2的方法。

@rockuw

// 原先只支持 callback 回调版:
var getInfo = function(uid, callback) {
    var sql = "select * from v_user where uid=? limit 1";
    Mysql.query(sql, [uid], function(err, row) {
        if(err) return callback(err);
        if(row.length===0) return callback();

        var info = row[0];
        callback(null, info);
    });
};
// 修改后 既支持 callback 回调,又支持 Promise
var getInfo = function(uid, callback) {
    return new Promise(function(resolve, reject) {
        if (callback) {
            resolve = function (ret) {
                callback(null, ret);
            };
            reject = callback;
        }

        var sql = "select * from v_user where uid=? limit 1";
        Mysql.query(sql, [uid], function(err, row) {
            if(err) return reject(err);
            if(row.length===0) return resolve();

            var info = row[0];
            resolve(info);
        });
    });
};

原文链接 你看看这种折中方案是否有可取之处?

@gzhangzy 他是为了兼容以前callback的接口,ali-oss之前没有callback的接口,没有兼容性问题。

而且使用方法上,我真觉得没什么区别:

client.put('object', '/tmp/file', function (err, data) {});
client.put('object', '/tmp/file').then(function (data) {}, function (err) {});

虽然从你的叙述里明显看出有情绪,但是作为在你上一篇帖子里第一个喷你的人,我就不说什么了。

你们确实倾听了客户意见,改进了你们的服务,而且对于一个大公司来说还不算慢。我想这也是阿里巴巴能够在云服务领域胜出的一个关键

比如我写 SDK,从来不考虑新特性。

就算 test 里面用了 const、let 什么的,在 src 里面还是会只用 es5 特性。

请问如下错误如何解决呢?

运行报错:

node_modules\ali-oss\lib\client.js:294 proto.request = function* (params) { ^ SyntaxError: Unexpected token * at Module._compile (module.js:439:25) at Object.Module._extensions…js (module.js:474:10 at Module.load (module.js:356:32) at Function.Module._load (module.js:312:12) at Module.require (module.js:364:17) at require (module.js:380:17)

楼上的,这个明显是不支持生成器这种特性啊,要么是你的node版本太低,要么是你用在了浏览器上。 node可以用4.4.7在生产环境上,本人及很多人都用着呢,不用怕的

client.put(‘object’, ‘/tmp/file’).then(function (val) { console.log(val.res); return client.get(‘object’); }).then(function (val) { console.log(val.res); console.log(val.content.toString()); });

请问下,上传文件这了的 put里面的 ‘object’,和‘/tmp/file’代表的是什么呀?

@alsotang 对 babel 无爱 -。 -

promise 只能解决部分问题,不能完全取代callback,。。 因为某个库只提供了promise方式,一些东西都写的我恶心死了。。。

回到顶部