初学 WinJS, 可能对 Promise 的用法不大清楚,本文简要说明一下 WinJS中 promise 的基本用法。

主要参考自:http://try.buildwinjs.com/#promises

Promise是 WinJS中实现异步模式编程的实现形式,

它其实更多的是一种规范,用来规范和简化 javascript 中的异步编程。

在promise被提出来之前,javascript中的异步编程通常是直接使用回调来完成的。

1
2
3
4
5
6
7
var getParentList = function (getParentListCallback) {
    // do get parent list data cost about 1 or more seconds
    // ...
    var parentList = XXX;
    // when get the data sucessfully, call the callback
    getParentListCallback(parentList);
}

使用的时候,就是这样的:

getParentList(function getParentListCallback(parentList) {
    // get children data according to the parentList data
    for (var i = 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) {
            var promiseArray = [];
            for (var i = 0; i < parentList.length; i++) {
                promiseArray.push(getChildrenList(parentList[i]));
            }
            return promiseArray.join();
        },
        function error() {
        })
    .then(
        function (chilrenList) {
            var promiseArray = [];
            for (var i = 0; i < chilrenList.length; i++) {
                promiseArray.push(getChildDetail(chilrenList[i]));
            }
            return promiseArray.join();
        },
        function error() {
        })
    .done(
        function (detailInfo) {
         
        },
        function error() {
        });

直观上看,promise让原来的代码嵌套层次少了,更加扁平可读了,而且逻辑功能上的suc和err处理放到一起了。

但 promise 并不仅仅这么简单。

个人理解,promise把原来的函数之间的嵌套调用,演化成了链式的关系。

.then ... .then 做为链中的一环,直到 .done,表示到了链的最后一环。(.done仅仅表明不再向后链接了,并不强制要求使用。)

所以说, promise其实本质上是一种规范,或者说是一种编程模式。

对于这个模式,各基于 javascript 的开发工具都有自己的实现,像 WinJS, NodeJs等。

WinJS的的 promise 是如何使用的呢?

首先,创建一个 promise:

项目开发中,对于比较耗时的操作,通常通过如下形式创建 promise 来执行:

// Do an add asynchronously (via setTimeout)
function asyncAdd(num1, num2) {
    return new WinJS.Promise(function (complete) {
        setTimeout(function () {
            var sum = 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 synchronously
function nonPromiseAdd(num1, num2) {
    return num1 + num2;
}
 
// wrap the regular non-synchronous method in Promise.as() to treat it as a promise
WinJS.Promise.as(nonPromiseAdd(3, 4)).
then(function (v){
    // 此处,v === 7
});

好,接下来的功能,就是 promise的强大之外了。

  1. 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。

  2. 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.");
    });
  3. 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 网站):

  1. 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');
        }
    });
  2. async.eachSeries. 同each类似,但是eachSeries可以保证针对每个 array里面的item, 执行functionForEachItem是顺执行,且只有前面的item执行完成,才会执行后面的item。

    async提供很多其它方便的功能,请大家https://github.com/caolan/async 了解更多,仔细查看,你会有一种只有想不到,没有做不到的感觉。

[WinJS] Promise 用法的更多相关文章

  1. c/c++ 多线程 等待一次性事件 std::promise用法

    多线程 等待一次性事件 std::promise用法 背景:不是很明白,不知道为了解决什么业务场景,感觉std::async可以优雅的搞定一切的一次等待性事件,为什么还有个std::promise. ...

  2. ES6语法 promise用法

    ES6语法 promise用法 function doSomething(){ return new Promise((resolve,reject)=>{ resolve('jjjj');// ...

  3. es6的promise用法详解

    es6的promise用法详解 promise 原理 promise是es6的异步编程解决方案, 是es6封装好的对象: 一个promise有三种状态:Pending(进行中).Resolved(已完 ...

  4. Es6 Promise 用法详解

     Promise是什么??    打印出来看看  console.dir(Promise) 这么一看就明白了,Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方 ...

  5. ES6 Promise 用法讲解

    Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方法,原型上有then.catch等同样很眼熟的方法. 那就new一个 var p = new Promise( ...

  6. Promise 用法

    Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方法,原型上有then.catch等同样很眼熟的方法. 那就new一个 Promise的构造函数接收一个参数,是 ...

  7. ES6 Promise用法讲解

    所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果. ES6 规定,Promise对象是一个构造函数,用来生成Promise实例. 下面代码创造了一个 ...

  8. ES6 Promise 用法转载

    Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方法,原型上有then.catch等同样很眼熟的方法. 那就new一个 var p = new Promise( ...

  9. promise用法详解

    es6的promise可谓是异步书写的一大福音,过去异步js书写是函数嵌套函数的方式,promise出现后书写异步js代码就变得美观得多了 以前的写法:回调函数不停嵌套 ajax('/banners' ...

随机推荐

  1. 使用wampserver安装Composer的注意事项

    http://getcomposer.org/Composer-Setup.exe 修改C:\wamp\bin\php\php5.3.10中php.ini中的配置 在php.ini中开启php_ope ...

  2. 【python自动化第一篇:python介绍与入门】

    一.python介绍以及发展史  1.1 python的介绍: 简单点来说吧,python这玩意儿是一个叫做Guido van Rossum的程序猿在1989年的圣诞打发时间而决心去开发的一个脚本编程 ...

  3. 基于OpenCV的人脸识别[iOS开发笔记(2)]

    开始了OpenCV的试水工作了... 1.Get ready 在OpenCV中我们会使用函数cv::CascadeClassifier 来进行人脸检测.但是在使用本函数之前我们需要添加一个XML文件对 ...

  4. 【iOS 7】使用UIScreenEdgePanGestureRecognizer实现swipe to pop效果

    在iOS 7还没有发布的时候,各种App实现各种的swipe to pop效果,比如这里有一份简单的demo. 在iOS 7上,只要是符合系统的导航结构: - (BOOL)application:(U ...

  5. group by是什么意思 mysql中

    mysql语法中group by是什么意思? 在百度中搜索半天,最后找到一篇解释比较好的(不是博文,是百度知道,很郁闷那么多网友怎么就没人解释的清楚),链接如下: http://zhidao.baid ...

  6. linux shell less 命令---转

    less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻 ...

  7. Mybatis下配置调用Oracle自定义函数返回的游标结果集

    在ibatis和Mybatis对存储过程和函数函数的调用的配置Xml是不一样的,以下是针对Mybatis 3.2的环境进行操作的. 第一步配置Mapper的xml内容 <mapper names ...

  8. 安装SQL Server2005出现 IIS警告原因

    出现此问题的原因取决于 SQL Server 的不是所有 IIS 7.0 组件都安装在计算机上.下表列出了受影响的组件. 组件 文件夹 静态内容 常见的 HTTP 功能 默认文档 常见的 HTTP 功 ...

  9. spring参数类型异常输出,SpringMvc参数类型转换错误输出

    spring参数类型异常输出, SpringMvc参数类型转换错误输出 >>>>>>>>>>>>>>>> ...

  10. 大数据应用:五大地区喜新厌旧游戏APP类别之比较与分析

    今天,我们来分享点不一样的资讯.....游戏APP之喜新厌旧排行榜!! 前阵子笔者开发了一套系统可以用来收集亚洲五大地区上架APP的每日排名信息,希望观察出五大地区在APP上的喜好和使用程度之间的相异 ...