Heim  >  Fragen und Antworten  >  Hauptteil

Schreiben Sie den Titel um: Wie konvertiere ich eine vorhandene Callback-API in ein Promise-Formular?

<p>Ich möchte Versprechen verwenden, um damit umzugehen, aber das Format meiner Rückruf-API ist wie folgt: </p> <h3>1. DOM-Laden oder andere einmalige Ereignisse: </h3> <pre class="brush:php;toolbar:false;">window.onload; // Als Rückruffunktion festlegen ... window.onload = function() { };</pre> <h3>2. Gewöhnliche Rückruffunktion: </h3> <pre class="brush:php;toolbar:false;">function request(onChangeHandler) { ... } request(function() { // geändert ... });</pre> <h3>3. Rückruffunktion im Node-Stil („nodeback“): </h3> <pre class="brush:php;toolbar:false;">function getStuff(dat, callback) { ... } getStuff("dataParam", function(err, data) { ... })</pre> <h3>4. Die gesamte Bibliothek verwendet Callback-Funktionen im Node-Stil: </h3> <pre class="brush:php;toolbar:false;">API; API.one(function(err, data) { API.two(function(err, data2) { API. three(function(err, data3) { ... }); }); });</pre> <h3>Wie verwende ich Versprechen, um mit dieser API umzugehen, und wie „verspreche“ ich sie? </h3>
P粉268654873P粉268654873425 Tage vor374

Antworte allen(2)Ich werde antworten

  • P粉618358260

    P粉6183582602023-08-22 16:14:21

    今天,我可以在Node.js中使用Promise作为一个普通的Javascript方法。

    一个简单和基本的Promise示例(使用KISS方法):

    普通的Javascript异步API代码:

    function divisionAPI (number, divider, successCallback, errorCallback) {
    
        if (divider == 0) {
            return errorCallback( new Error("Division by zero") )
        }
    
        successCallback( number / divider )
    
    }

    Promise的Javascript异步API代码:

    function divisionAPI (number, divider) {
    
        return new Promise(function (fulfilled, rejected) {
    
            if (divider == 0) {
                return rejected( new Error("Division by zero") )
            }
    
            fulfilled( number / divider )
    
         })
    
    }

    (我推荐访问这个优秀的来源

    此外,Promise也可以与ES7中的async\await一起使用,使程序流程等待fulfilled结果,如下所示:

    function getName () {
    
        return new Promise(function (fulfilled, rejected) {
    
            var name = "John Doe";
    
            // 在调用fulfilled()方法之前等待3000毫秒
            setTimeout ( 
                function() {
                    fulfilled( name )
                }, 
                3000
            )
    
        })
    
    }
    
    
    async function foo () {
    
        var name = await getName(); // 等待fulfilled结果!
    
        console.log(name); // 控制台在3000毫秒后输出"John Doe"
    
    }
    
    
    foo() // 调用foo()方法运行代码

    使用相同的代码,可以使用.then()方法:

    function getName () {
    
        return new Promise(function (fulfilled, rejected) {
    
            var name = "John Doe";
    
            // 在调用fulfilled()方法之前等待3000毫秒
            setTimeout ( 
                function() {
                    fulfilled( name )
                }, 
                3000
            )
    
        })
    
    }
    
    
    // 控制台在3000毫秒后输出"John Doe"
    getName().then(function(name){ console.log(name) })

    Promise也可以在任何基于Node.js的平台上使用,比如react-native

    额外奖励:一种混合方法
    (假设回调方法有两个参数,分别是错误和结果)

    function divisionAPI (number, divider, callback) {
    
        return new Promise(function (fulfilled, rejected) {
    
            if (divider == 0) {
                let error = new Error("Division by zero")
                callback && callback( error )
                return rejected( error )
            }
    
            let result = number / divider
            callback && callback( null, result )
            fulfilled( result )
    
         })
    
    }

    上述方法可以同时响应旧式的回调和Promise用法的结果。

    希望这能帮到你。

    Antwort
    0
  • P粉680087550

    P粉6800875502023-08-22 11:07:09

    承诺具有状态,它们开始时处于挂起状态,可以解决为:

    • 已实现表示计算成功完成。
    • 已拒绝表示计算失败。

    返回承诺的函数不应该抛出异常,而应该返回拒绝。从返回承诺的函数中抛出异常将强制您同时使用} catch { .catch。使用承诺化的API的人们不希望承诺抛出异常。如果您不确定JS中的异步API如何工作,请首先查看此答案

    1. DOM加载或其他一次性事件:

    因此,创建承诺通常意味着指定它们何时解决-这意味着它们何时移动到已实现或已拒绝阶段以指示数据可用(并可使用.then访问)。

    使用支持Promise构造函数的现代承诺实现(如原生ES6承诺):

    function load() {
        return new Promise(function(resolve, reject) {
            window.onload = resolve;
        });
    }

    然后您可以这样使用生成的承诺:

    load().then(function() {
        // 在onload之后执行操作
    });

    使用支持延迟(这里我们使用$q作为示例,但稍后我们还将使用jQuery)的库:

    function load() {
        var d = $q.defer();
        window.onload = function() { d.resolve(); };
        return d.promise;
    }

    或者使用类似于jQuery的API,钩住一次发生的事件:

    function done() {
        var d = $.Deferred();
        $("#myObject").once("click",function() {
            d.resolve();
        });
        return d.promise();
    }

    2. 普通回调:

    这些API相当常见,因为在JS中回调很常见。让我们看看常见情况下的onSuccessonFail

    function getUserData(userId, onLoad, onFail) { …

    使用支持Promise构造函数的现代承诺实现(如原生ES6承诺):

    function getUserDataAsync(userId) {
        return new Promise(function(resolve, reject) {
            getUserData(userId, resolve, reject);
        });
    }

    使用支持延迟(这里我们使用jQuery作为示例,但我们之前也使用了$q)的库:

    function getUserDataAsync(userId) {
        var d = $.Deferred();
        getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
        return d.promise();
    }

    jQuery还提供了$.Deferred(fn)形式,它的优点是允许我们编写一个非常接近new Promise(fn)形式的表达式,如下所示:

    function getUserDataAsync(userId) {
        return $.Deferred(function(dfrd) {
            getUserData(userId, dfrd.resolve, dfrd.reject);
        }).promise();
    }

    注意:这里我们利用了jQuery延迟的resolvereject方法是“可分离”的事实;即它们绑定到jQuery.Deferred()的实例。并非所有库都提供此功能。

    3. Node风格回调("nodeback"):

    Node风格回调(nodebacks)具有特定的格式,其中回调始终是最后一个参数,其第一个参数是错误。首先手动将其转换为承诺:

    getStuff("dataParam", function(err, data) { …

    转换为:

    function getStuffAsync(param) {
        return new Promise(function(resolve, reject) {
            getStuff(param, function(err, data) {
                if (err !== null) reject(err);
                else resolve(data);
            });
        });
    }

    使用延迟,您可以执行以下操作(我们使用Q作为示例,尽管Q现在支持新语法您应该优先选择该语法):

    function getStuffAsync(param) {
        var d = Q.defer();
        getStuff(param, function(err, data) {
            if (err !== null) d.reject(err);
            else d.resolve(data);
        });
        return d.promise;   
    }

    一般来说,您不应该手动过多地将事物转换为承诺,大多数针对Node设计的承诺库以及Node 8+中的原生承诺都具有用于将nodebacks转换为承诺的内置方法。例如

    var getStuffAsync = Promise.promisify(getStuff); // Bluebird
    var getStuffAsync = Q.denodeify(getStuff); // Q
    var getStuffAsync = util.promisify(getStuff); // 原生承诺,仅限Node

    4. 整个库使用Node风格回调:

    这里没有黄金法则,您可以逐个将它们转换为承诺。但是,某些承诺实现允许您批量执行此操作,例如在Bluebird中,将nodeback API转换为承诺API就像这样简单:

    Promise.promisifyAll(API);

    或在Node中使用原生承诺

    const { promisify } = require('util');
    const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)}))
                             .reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});

    注意:

    • 当您在.then处理程序中时,当然不需要将事物转换为承诺。从.then处理程序返回一个承诺将使用该承诺的值解决或拒绝。从.then处理程序中抛出异常也是良好的实践,将拒绝该承诺-这就是著名的承诺抛出安全性。
    • 在实际的onload情况中,您应该使用addEventListener而不是onX

    Antwort
    0
  • StornierenAntwort