zoukankan      html  css  js  c++  java
  • [WinJS] Promise 用法

    初学 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 了解更多,仔细查看,你会有一种只有想不到,没有做不到的感觉。
  • 相关阅读:
    TCP/IP讲解
    Android开发的技术层次
    页面右下角弹出类似QQ或MSN的消息提示
    C# winform 自定义鼠标图标
    C#遍历指定文件夹中的所有文件
    C#操作Word
    关于数据绑定的一些小技巧
    Silverlight遍历本地文件夹
    ckeditor+ckfinder+syntaxhighlight实现上传和插入代码高亮(for .NET)
    wpf 动画效果
  • 原文地址:https://www.cnblogs.com/aaron-lau/p/4193577.html
Copyright © 2011-2022 走看看