[WinJS] Promise 用法
初学 WinJS, 可能对 Promise 的用法不大清楚,本文简要说明一下 WinJS中 promise 的基本用法。
主要参考自:http://try.buildwinjs.com/#promises
Promise是 WinJS中实现异步模式编程的实现形式,
它其实更多的是一种规范,用来规范和简化 javascript 中的异步编程。
在promise被提出来之前,javascript中的异步编程通常是直接使用回调来完成的。
| 1 2 3 4 5 6 7 | vargetParentList = function(getParentListCallback) {    // do get parent list data cost about 1 or more seconds    // ...    varparentList = XXX;    // when get the data sucessfully, call the callback    getParentListCallback(parentList);} | 
使用的时候,就是这样的:
| getParentList(functiongetParentListCallback(parentList) {    // get children data according to the parentList data    for(vari = 0; i < parentList.length; i++) {        //        getChildrenList(parentList[i]);    }}); | 
一个函数执行可能会花费比较长的时间,逻辑上不需要等待这个函数返回,就可以执行后面的代码,
这是非常常见的场景,使用上面回调函数的方法,完全可以解决问题。
但如果场景更复杂一些,或者需要考虑更多的情况,例如异常处理,根据不同的返回值,调用不同的回调函数,
就会发现这种写法非常的ugly。如果有三层回调的话,代码可能是这样的:
| getParentList(    // success callback    function getParentListCallback(parentList) {        // get children data according to the parentList data        for(var i = 0; i < parentList.length; i++) {            //            getChildrenList(parentList[i],                // success callback                function getChildrenListCallback(childrenList) {                    for(var j = 0; j < childrenList.length; j++) {                        getChildDetail(childrenList[j],                            // success callback                            function getChildDetailCallback(detailInfo) {                            },                            // error callback                            function errorCallback() {                            })                    }                },                // error callback                function errorCallback() {                });        }    },    // error callback    function errorCallback() {        // Do something to handle the error    }); | 
感觉如何?同一逻辑的的suc和error隔着很多其它的代码,代码的嵌套层次还特别深,
这还是在大部分逻辑没有展开的情况下看到的样子呢,如果在实际项目中使用,逻辑全部展开,最终的代码估计自己写完都不想再看第二遍。
OK,promise来了,promise有个 Promises/A+ 实现规范,有兴趣的可以抽时间看下。
现在,我们直接看下使用 promise 后的代码:
| getParentList()    .then(        function(parentList) {            varpromiseArray = [];            for(vari = 0; i < parentList.length; i++) {                promiseArray.push(getChildrenList(parentList[i]));            }            returnpromiseArray.join();        },        functionerror() {        })    .then(        function(chilrenList) {            varpromiseArray = [];            for(vari = 0; i < chilrenList.length; i++) {                promiseArray.push(getChildDetail(chilrenList[i]));            }            returnpromiseArray.join();        },        functionerror() {        })    .done(        function(detailInfo) {                },        functionerror() {        }); | 
直观上看,promise让原来的代码嵌套层次少了,更加扁平可读了,而且逻辑功能上的suc和err处理放到一起了。
但 promise 并不仅仅这么简单。
个人理解,promise把原来的函数之间的嵌套调用,演化成了链式的关系。
.then ... .then 做为链中的一环,直到 .done,表示到了链的最后一环。(.done仅仅表明不再向后链接了,并不强制要求使用。)
所以说, promise其实本质上是一种规范,或者说是一种编程模式。
对于这个模式,各基于 javascript 的开发工具都有自己的实现,像 WinJS, NodeJs等。
WinJS的的 promise 是如何使用的呢?
首先,创建一个 promise:
项目开发中,对于比较耗时的操作,通常通过如下形式创建 promise 来执行:
| // Do an add asynchronously (via setTimeout)functionasyncAdd(num1, num2) {    returnnewWinJS.Promise(function(complete) {        setTimeout(function() {            varsum = num1 + num2;            // this promise is completed when the complete() function is called which also            // returns the value (result) of the promise.            complete(sum);        }, 1000);    });} | 
这样,使用时,即可如下使用:
| asyncAdd(1, 2).    then(function(v) {       // 此处,v === 3    }) | 
然后,我们可能已经有了一个同步执行的函数,如何让它以promise的形式来调用它呢?
如下进行:
| // add two numbers together synchronouslyfunctionnonPromiseAdd(num1, num2) {    returnnum1 + num2;}// wrap the regular non-synchronous method in Promise.as() to treat it as a promiseWinJS.Promise.as(nonPromiseAdd(3, 4)).then(function(v){    // 此处,v === 7}); | 
好,接下来的功能,就是 promise的强大之外了。
- promise之 cancel。 异步操作时,通常会遇到上下文,或者说场景,context已经失效了,异步操作还没有完成,或者异步操作完成了,但context失效,已经没有意义了。相信大家都有自己的解决方法。使用 promise的话,很简单,直接把 promise cancel掉就行了。 - var- loadImagePromise = WinJS.Promise.as(loadImage());- function- unload() {- loadImagePromise.cancel();- }- 有一点需要注意的是,promise执行过程中被cancel掉的话,promise.then会被调用,这时候需要判断 promise的状态,promise._state.name 的值,可能是success,或者是canceled。 
- promise之join。多个异步操作同时执行的话,就会有异步操作之前协调的问题。promise.join提供一个promise的数组做参数,表示这个数组中的所有promise都执行完成后,promise.join才会视为执行完成,即 promise.join(promiseArray).then(){}中的then才会被执行。 - var- p = [];- var- index = 0;- // create a promise that completes in 2000ms, then add it to the promise array- p[index++] = WinJS.Promise.timeout(2000).- then(- function- () {- output(- "<br/> First promise is fullfilled after 2 seconds"- );- }- );- // create a promise that completes in 3000ms, then add it to the promise array- p[index++] = WinJS.Promise.timeout(3000).- then(- function- () {- output(- "<br/> Second promise is fullfilled after 3 seconds"- );- }- );- // pass the promise array to Promise.join() to create a promise that will not be completed until all- // promises have been completed.- WinJS.Promise.join(p).- then(- function- () {- output(- "<br/> Calling join will ensure this function will not be called until the both promises have been completed."- );- });
- promise之any。同上类似的场景,如果要求 promise数组中,任意一个promise执行完成即可的话,就使用promise.any。
OK,上面仅是 WinJS支持的 promise功能。由于 javascript的开源特性,很多其它基于js的工具包中的 promise,是可以直接拿来使用的(在遵守开源许可的情况下,把代码引入到我们的项目中即可)。所以我们可以非常方便的使用诸如 NodeJS里面的promise功能。为什么要使用他们的呢,他山之石,可以攻玉,比如我们项目中常用的 Async.js (https://github.com/caolan/async),是为NodeJS设计使用的,但它没有第三方依赖,实现代码只有一个 js 文件,可以直接引用,它的promise提供以下常用功能(仅列举常用,详细请参数 Anync.js的 github 网站):
- async.each。async不需要手动创建promise,它支持直接以数组为参数。async.each的函数原型如下: - each(array, functionForEachItem, errorCallback)- 针对每个 array里面的item, 都会执行一次functionForEachItem, 使用起来是这样的: - // assuming openFiles is an array of file names- async.each(openFiles,- function- ( file, callback) {- // Perform operation on file here.- console.log(- 'Processing file '- + file);- if- ( file.length > 32 ) {- console.log(- 'This file name is too long'- );- callback(- 'File name too long'- );- }- else- {- // Do work to process file here- console.log(- 'File processed'- );- callback();- }- },- function- (err){- // if any of the file processing produced an error, err would equal that error- if- ( err ) {- // One of the iterations produced an error.- // All processing will now stop.- console.log(- 'A file failed to process'- );- }- else- {- console.log(- 'All files have been processed successfully'- );- }- });
- async.eachSeries. 同each类似,但是eachSeries可以保证针对每个 array里面的item, 执行functionForEachItem是顺执行,且只有前面的item执行完成,才会执行后面的item。
async提供很多其它方便的功能,请大家https://github.com/caolan/async 了解更多,仔细查看,你会有一种只有想不到,没有做不到的感觉。 
[WinJS] Promise 用法的更多相关文章
- c/c++ 多线程 等待一次性事件 std::promise用法
		多线程 等待一次性事件 std::promise用法 背景:不是很明白,不知道为了解决什么业务场景,感觉std::async可以优雅的搞定一切的一次等待性事件,为什么还有个std::promise. ... 
- ES6语法 promise用法
		ES6语法 promise用法 function doSomething(){ return new Promise((resolve,reject)=>{ resolve('jjjj');// ... 
- es6的promise用法详解
		es6的promise用法详解 promise 原理 promise是es6的异步编程解决方案, 是es6封装好的对象: 一个promise有三种状态:Pending(进行中).Resolved(已完 ... 
- Es6 Promise 用法详解
		Promise是什么?? 打印出来看看 console.dir(Promise) 这么一看就明白了,Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方 ... 
- ES6 Promise 用法讲解
		Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方法,原型上有then.catch等同样很眼熟的方法. 那就new一个 var p = new Promise( ... 
- Promise 用法
		Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方法,原型上有then.catch等同样很眼熟的方法. 那就new一个 Promise的构造函数接收一个参数,是 ... 
- ES6 Promise用法讲解
		所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果. ES6 规定,Promise对象是一个构造函数,用来生成Promise实例. 下面代码创造了一个 ... 
- ES6 Promise 用法转载
		Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方法,原型上有then.catch等同样很眼熟的方法. 那就new一个 var p = new Promise( ... 
- promise用法详解
		es6的promise可谓是异步书写的一大福音,过去异步js书写是函数嵌套函数的方式,promise出现后书写异步js代码就变得美观得多了 以前的写法:回调函数不停嵌套 ajax('/banners' ... 
随机推荐
- radix树
			今天在学Linux内核页高速缓存时,学到了一种新的数据结构radix树(基数),经过分析,感觉此数据结构有点鸡肋,有可能是我理解不到位吧. 先来张图,给大家以直观的印象 当有一个key-value型的 ... 
- C#封装加密算法(MD5、SHA、HMAC、DES、RSA)的一个类
			using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace Wen. ... 
- 利用ServletFileUpload组件上传文件
			自己的运用: public void UploadNoteFile(HttpServletRequest request,HttpServletResponse response){ String ... 
- LabVIEW设计模式系列——case结构模拟事件结构
			标准:1.所有按钮的机械动作必须都用释放时触发或者单击时触发,这是为了保证仅仅触发一次动作. 标准:1.使用简单的case结构模拟事件结构. 
- FileZilla命令行实现文件上传以及CreateProcess实现静默调用
			应用需求: 用户在选择渲染作业时面临两种情况:一是选择用户远程存储上的文件:二是选择本地文件系统中的文件进行渲染.由于渲染任务是在远程主机上进行的,实际进行渲染时源文件也是在ftp目录 ... 
- linux find grep使用
			在当前目录下所有文件中查找内容包含 string 的文件: find ./ -name "*" -exec grep "string" {} \; 注意:在最后 ... 
- 微信分组群发图文40152,微信分组群发图文invalid group id hint
			微信分组群发40152,微信分组群发invalid group id hint >>>>>>>>>>>>>>> ... 
- C# 事件的理解
			说实话,事件弄得还是很晕,有待于以后的强化吧,下面是我对事件的一点理解 首先,参见大牛的帖子:网上大牛事件讲解 下面我来说一说事件的大致流程: 事件委托事件概述事件就是当对象或类状态发生改变时,对象或 ... 
- JS2 for应用
			for应用 再谈js获取元素一二: var oUl=document.getElementById('list'); //静态方法 var oUl=document.getElements ... 
- [Json] C#ConvertJson|List转成Json|对象|集合|DataSet|DataTable|DataReader转成Json (转载)
			点击下载 ConvertJson.rar 本类实现了 C#ConvertJson|List转成Json|对象|集合|DataSet|DataTable|DataReader转成Json|等功能大家先预 ... 
