WinJS,从中可以或不可以是异步函数返回一个许 [英] WinJS, return a promise from a function which may or may not be async

查看:159
本文介绍了WinJS,从中可以或不可以是异步函数返回一个许的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的WinJS应用程序想要调用可能会或可能不会是异步(例如:在一种情况下,我需要从一个文件(异步加载某些数据),但在其他时间,我可以从缓存中加载功能的情况下syncronously)。

I have a situation where my WinJS app wants to call a function which may or may not be async (e.g. in one situation I need to load some data from a file (async) but at other times I can load from a cache syncronously).

有通过文档看看我,虽然我可以换有条件的逻辑就像一个承诺:

Having a look through the docs I though I could wrap the conditional logic in a promise like:

A)
return new WinJS.Promise(function() {  // mystuff });

或者可能使用'为'是这样的:

or possibly use 'as' like this:

B)
return WinJS.Promise.as(function() { // mystuff });

问题是,当我调用此函数,这我是从我的第一页这样就绪()函数,这样做的:

The problem is that when I call this function, which I'm doing from the ready() function of my first page like this:

WinJS.UI.Pages.define("/pages/home/home.html", {

    ready: function () {

         Data.Survey.init().done(function (result) {

            // do some stuff with 'result'

        });
    }
 });

当它是这样写的'A'它永远不会打我()完成调用。

When it is written like 'A' it never hits my done() call.

或者,如果我把它时,它写的'B',它()立即执行code里面我做的,承诺解决之前。它也看起来与结果的价值,它刚刚被设置为我的init()函数,的内容,而不是在一个承诺被包裹起来。

Or if I call it when it's written like 'B', it executes the code inside my done() instantly, before the promise is resolved. It also looks from the value of result, that it has just been set to the content of my init() function, rather than being wrapped up in a promise.

这感觉就像我在这里做得相当基本上是没错的,但我不能确定从哪里开始寻找。

It feels like I'm doing something quite basically wrong here, but I'm unsure where to start looking.

如果它的任何帮助,这是我的init的简化版本()函数:

If it's any help, this is a slimmed down version of my init() function:

    function init() {

    return new WinJS.Promise(function() {

        if (app.context.isFirstRun) {

            app.surveyController.initialiseSurveysAsync().then(function (result) {
                return new WinJS.Binding.List(result.surveys);
            });
        } else {

            var data = app.surveyController.getSurveys();
            return new WinJS.Binding.List(data);
        }
    });
}  

有没有人对这个有什么想法?我不相信'可能会或可能不会是异步'是这里的问题,我相信诺言的设置是不是做我的期望。任何人都可以看到什么明显的错误吗?任何反馈大大AP preciated。

Does anyone have any thoughts on this one? I don't believe the 'may or may not be async' is the issue here, I believe the promise setup isn't doing what I'd expect. Can anyone see anything obviously wrong here? Any feedback greatly appreciated.

推荐答案

一般来说,如果你正在做的文件I / O在你的全初始化例程,这些API返回自己的承诺,在这种情况下,要返回之一这些承诺或的方法。然后一个承诺。

Generally speaking, if you're doing file I/O in your full init routine, those APIs return promises themselves, in which case you want to return one of those promises or a promise from one of the .then methods.

WinJS.Promise.as,另一方面,是指在一个承诺来包装的值。但让我更充分的解释。

WinJS.Promise.as, on the other hand, is meant to wrap a value in a promise. But let me explain more fully.

首先,请阅读仔细WinJS.Promise构造函数的文档。和许多人一样,你错误地假设你刚换了一块code的承诺,瞧!这是异步。不是这种情况。您传递给构造函数是一个的初始化的接收三个参数:一个completeDispatcher功能,一个errorDispatcher功能和progressDispatcher功能,因为我喜欢给他们打电话

First, read the documentation for the WinJS.Promise constructor carefully. Like many others, you're mistakenly assuming that you just wrap a piece of code in the promise and voila! it is async. This is not the case. The function that you pass to the constructor is an initializer that receives three arguments: a completeDispatcher function, an errorDispatcher function, and a progressDispatcher function, as I like to call them.

有关承诺永远成功完成,完成错误,或报告进度,有必要在初始化的code的其余部分最终调用调度员之一。这些调度员,承诺,再通过循环,并呼吁已给予该承诺的那么做,或任何方法完成/错误/进度的方法里面。因此,如果你不叫在​​所有的调度程序,也没有完成,而这正是你所看到的行为。

For the promise to ever complete with success, complete with an error, or report progress, it is necessary for the rest of the code in the initializer to eventually call one of the dispatchers. These dispatchers, inside the promise, then loop through and call any complete/error/progress methods that have been given to that promise's then or done methods. Therefore, if you don't call a dispatcher at all, there is no completion, and this is exactly the behavior you're seeing.

使用WinJS.Promise.as类似,它包装了一个的的承诺中。在你的情况,如果你传递给WinJS.promise.as功能,你会得到的是与该函数值作为结果实现的承诺。你做的的获取函数的异步执行。

Using WinJS.Promise.as is similar in that it wraps a value inside a promise. In your case, if you pass a function to WinJS.promise.as, what you'll get is a promise that's fulfilled with that function value as a result. You do not get async execution of the function.

要实现异步行为,您必须使用的setTimeout / setInterval的(或在Windows 8.1中的WinJS调度程序)进行异步工作在UI线程上,或者使用一个网络工作者后台线程,并配合其完成(通过postMessage的)成一个承诺。

To achieve async behavior you must either use setTimeout/setInterval (or the WinJS scheduler in Windows 8.1) to do async work on the UI thread, or use a web worker for a background thread and tie its completion (via a postMessage) into a promise.

下面是使用构造函数创建一个承诺,处理完整,错误和进步的情况下一个完整的示例(以及取消):

Here's a complete example of creating a promise using the constructor, handling complete, error, and progress cases (as well as cancellation):

    function calculateIntegerSum(max, step) {
    if (max < 1 || step < 1) {
        var err = new WinJS.ErrorFromName("calculateIntegerSum", "max and step must be 1 or greater");
        return WinJS.Promise.wrapError(err);
    }

    var _cancel = false;

    //The WinJS.Promise constructor's argument is a function that receives 
    //dispatchers for completed, error, and progress cases.
    return new WinJS.Promise(function (completeDispatch, errorDispatch, progressDispatch) {
        var sum = 0;

        function iterate(args) {
            for (var i = args.start; i < args.end; i++) {
                sum += i;
            };

            //If for some reason there was an error, create the error with WinJS.ErrorFromName
            //and pass to errorDispatch
            if (false /* replace with any necessary error check -- we don’t have any here */) {
                errorDispatch(new WinJS.ErrorFromName("calculateIntegerSum", "error occurred"));
            }

            if (i >= max) {
                //Complete--dispatch results to completed handlers
                completeDispatch(sum);
            } else {
                //Dispatch intermediate results to progress handlers
                progressDispatch(sum);

                //Interrupt the operation if canceled
                if (!_cancel) {
                    setImmediate(iterate, { start: args.end, end: Math.min(args.end + step, max) });
                }
            }
        }

        setImmediate(iterate, { start: 0, end: Math.min(step, max) });
    },
    //Cancellation function 
    function () {
        _cancel = true;
    });
}

这是来自我的免费电子书的附录A(解密用),编程Windows应用商店的应用程序的HTML,CSS和JavaScript,第二版(在preVIEW),看的 http://aka.ms/BrockschmidtBook2

This comes from Appendix A ("Demystifying Promises") of my free ebook, Programming Windows Store Apps in HTML, CSS, and JavaScript, Second Edition (in preview), see http://aka.ms/BrockschmidtBook2.

您会在你的情况下,把你的数据初始化code在迭代函数的地方,或许从setImmediate中调用它。我鼓励你也看WinJS调度API,它可以让你在UI线程的工作设置优先级。

You would, in your case, put your data initialization code in the place of the iterate function, and perhaps call it from within a setImmediate. I encourage you to also look at the WinJS scheduler API that would let you set the priority for the work on the UI thread.

总之,要明白的新WinJS.Promise 的和的 WinJS.Promise.as 的本身并不创造异步行为,承诺本身只是一个通话非常必要会议围绕结果稍后发表有什么本质上是与异步。

In short, it's essential to understand that new WinJS.Promise and WinJS.Promise.as do not in themselves create async behavior, as promises themselves are just a calling convention around "results to be delivered later" that has nothing inherently to do with async.

这篇关于WinJS,从中可以或不可以是异步函数返回一个许的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆