理解JavaScript中的promise

我编写了很多JavaScript代码,尽管我认为我确实理解了promises的工作方式,但我不确定我是否完全理解了承诺给JS世界带来的好处.考虑下面的代码,简单地使用包含调用调用的回调进行异步调用,依此类推.

(function doWorkOldSchool() {

    setTimeout(function() {

        // once done resolve promise

        console.log("work done");

        setTimeout(function goHome() {

            // once done resolve promise

            console.log("got home");

            try {

                setTimeout(function cookDinner() {

                    // this exception will not be caught

                    throw "No ingredients for dinner!";
                    console.log("dinner cooked");

                    setTimeout(function goToSleep() {

                        // once done resolve promise

                        console.log("go to sleep");

                    }, 2000);

                }, 2000);

            } catch (ex) {
                console.log(ex);
            }

        }, 2000);

    }, 2000);

}());

我看到的一个问题是:

>回调中抛出的异常是无用的.是否正确的说,当抛出调用发生时,这些抛出调用超出范围,因此异常无法调用并且一直冒泡到顶部?如何处理这种异常?
>第二个问题我看到这个嵌套业务可能会变得非常深,即使你可以在setTimeout代码之外保留回调函数代码,它也可能变得一团糟.

首先,有人可以澄清是否还有其他任何明显的问题或这种编码的优势?

现在,下面我准备的程序真的做了同样的事情,但这次使用promises:

function doWork() {

    return new Promise(function(res, rej) {

        // do your asynchronous stuff

        setTimeout(function() {

            // once done resolve promise

            res("work done");

        }, 2000);

    });
}


function goHome(succ) {

    console.log(succ);

    return new Promise(function(res, rej) {

        // do your asynchronous stuff

        setTimeout(function() {

            // once done resolve promise

            res("got home");

        }, 2000);

    });
}


function cookDinner(succ) {

    console.log(succ);

    //if exception thrown here it will be caught by chained err handler
    throw "No ingredients for dinner Exception!";

    return new Promise(function(res, rej) {

        // do your asynchronous stuff

        setTimeout(function() {

            // something went wrong so instead of using throw we reject the promise

            rej("No ingredients for dinner!");

            // once done resolve promise

        }, 2000);

    });
}


function goToSleep(succ) {

    console.log(succ);

    return new Promise(function(res, rej) {

        // do your asynchronous stuff

        setTimeout(function() {

            // once done resolve promise

            res("zzz... zz..");

        }, 2000);

    });
}


doWork()
    .then(goHome)
    .then(cookDinner)
    .then(goToSleep)
    .then(function(succ) {

        console.log(succ);

    }, function(err) {
        console.log(err);
    });

与之前的解决方案相比,我发现这种方法没有明显的问题,除了你显然必须理解承诺编码/维护这个东西.然而,优点是:

>抛出的异常INSIDE OF处理程序将被捕获在更进一步链接的错误处理程序中.
>被拒绝的Promise将被链式错误处理程序捕获
>代码更清洁

现在,我的理解是正确的还是每种方法都有其他优点/缺点?

解决方法:

您的代码使用了一些反模式,您永远不应该在应用程序代码中创建承诺(例如,通过新的Promise,“deferreds”等).你也必须永远不要将回调与promises混合,因为这样你就会失去异常冒泡(承诺点)并使你的代码变得非常冗长.

您可以使用库或自己实现延迟:

function delay(ms, val) {
     return new Promise(function(res){setTimeout(res.bind(null, val), ms);});
}

然后:

function doWork() {
    return delay(2000, "work done");
}

doWork()
    .then(function(succ) {
        console.log(succ);
        return delay(2000, "got home");
    })
    .then(function(succ) {
        console.log(succ);
        // Never throw strings, yet another anti-pattern
        throw new Error("No ingredients for dinner Exception!");
        // Pointless to add code after throw
    })
    .then(function(succ) {
        return delay(2000, "zzz.. zz..");
    })
    // Don't use the second argument of .then, use .catch
    .catch(function(err) {
        console.log("error: ", err);
    });

为什么要使用.catch而不是第二个参数?那么,与你同步编写它的方式相比:

try {
    doWork();
    console.log("work done");
    sleep(2000);
    console.log("got home");
    sleep(2000);
    throw new Error("No ingredients for dinner Exception!";)
    sleep(2000);
    console.log("zzz.. zz..");
}
catch(e) {
    console.log("error: ", err);
}

得到它?

相关文章

最后的控制台返回空数组.控制台在ids.map函数完成之前运行va...
我正在尝试将rxJava与我已经知道的内容联系起来,特别是来自J...
config.jsconstconfig={base_url_api:"https://douban....
我正在阅读MDN中的javascript,并且遇到了这个谈论承诺并且不...
config.jsconstconfig={base_url_api:"https://douban....
这是我的代码main.cpp:#include<string>#include<...