875 Stimmen

Wie konvertiere ich eine vorhandene Rückruf-API in Promises?

Ich möchte mit Promises arbeiten, habe aber eine Callback-API in einem Format wie:

1. DOM load oder andere einmalige Ereignisse:

window.onload; // auf callback setzen
...
window.onload = function() {

};

2. Einfacher Callback:

function request(onChangeHandler) {
    ...
}
request(function() {
    // Änderung erfolgte
    ...
});

3. Node-Style-Callback ("nodeback"):

function getStuff(dat, callback) {
    ...
}
getStuff("dataParam", function(err, data) {
    ...
})

4. Eine ganze Bibliothek mit Node-Style-Callbacks:

API;
API.one(function(err, data) {
    API.two(function(err, data2) {
        API.three(function(err, data3) {
            ...
        });
    });
});

Wie arbeite ich mit der API mit Promises, wie 'promisify' ich sie?

26voto

Josiah Nyarega Punkte 615

Eine einfache generische Funktion, die ich normalerweise verwende.

const promisify = (fn, ...args) => {
  return new Promise((resolve, reject) => {
    fn(...args, (err, data) => {
      if (err) {
        return reject(err);
      }
      resolve(data);
    });
  });
};

Wie man es benutzt

  • Die Funktion promisify akzeptiert eine Funktion mit einem Rückruf (Callback):

    const cb = (result) => Das Ergebnis lautet ${result};

    const sum = (a, b, cb) => { const result = a + b; cb(result); // Args an die Rückruffunktion übergeben }

    // Verwendung des Dienstprogramms promise = promisify(sum, 3, 1, cb); promise.then(x => console.log(x)) // 4

Übersetzt von Ihnen wahrscheinlich nicht gesucht, aber dies wird helfen, das Innenleben der verfügbaren Hilfsprogramme zu verstehen

16voto

Bruno Punkte 5951

In der Release-Kandidat für Node.js 8.0.0 gibt es ein neues Dienstprogramm, util.promisify (über das ich schon geschrieben habe util.promisify), das die Fähigkeit besitzt, jede Funktion zu promisifizieren.

Es unterscheidet sich nicht viel von den in den anderen Antworten vorgeschlagenen Ansätzen, hat aber den Vorteil, eine Kernmethode zu sein und keine zusätzlichen Abhängigkeiten zu erfordern.

const fs = require('fs');
const util = require('util');

const readFile = util.promisify(fs.readFile);

Dann haben Sie eine Methode readFile, die ein nativer Promise zurückgibt.

readFile('./notes.txt')
  .then(txt => console.log(txt))
  .catch(...);

9voto

daviddavis Punkte 263

Mit einfachem alten Vanilla JavaScript hier ist eine Lösung, um einen API-Callback zu promisifizieren.

function get(url, callback) {
        var xhr = new XMLHttpRequest();
        xhr.open('get', url);
        xhr.addEventListener('readystatechange', function () {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    console.log('erfolgreich ... sollte callback aufrufen ... ');
                    callback(null, JSON.parse(xhr.responseText));
                } else {
                    console.log('Fehler ... callback mit Fehlerdaten ... ');
                    callback(xhr, null);
                }
            }
        });
        xhr.send();
    }

/**
     * @function promisify: wandelt API-basierte Callbacks in Promises um
     * @description nimmt eine Factory-Funktion entgegen und macht sie zu einem Promise
     * @params {function} Eingabefunktion zum Promisifizieren
     * @params {array} ein Array von Eingaben für die zu promisifizierende Funktion
     * @return {function} promisifizierte Funktion
     * */
    function promisify(fn) {
        return function () {
            var args = Array.prototype.slice.call(arguments);
            return new Promise(function(resolve, reject) {
                fn.apply(null, args.concat(function (err, result) {
                    if (err) reject(err);
                    else resolve(result);
                }));
            });
        }
    }

var get_promisified = promisify(get);
var promise = get_promisified('some_url');
promise.then(function (data) {
        // entspricht der Resolve-Funktion
        console.log('erfolgreiche Operation: ', data);
}, function (error) {
        console.log(error);
});

9voto

Apoorv Punkte 232

Sie können native JavaScript-Versprechen mit Node JS verwenden.

Mein Cloud 9 Code-Link: https://ide.c9.io/adx2803/native-promises-in-node

/**
* Erstellt von dixit-lab am 20.6.16.
*/

var express = require('express');
var request = require('request');   // Vereinfachter HTTP-Anforderungsclient.

var app = express();

function promisify(url) {
    return new Promise(function (resolve, reject) {
        request.get(url, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                resolve(body);
            }
            else {
                reject(error);
            }
        })
    });
}

// Alle Alben eines Benutzers abrufen, der Beitrag 100 veröffentlicht hat
app.get('/listAlbums', function (req, res) {
    // Den Beitrag mit der Beitrag-ID 100 abrufen
    promisify('http://jsonplaceholder.typicode.com/posts/100').then(function (result) {
        var obj = JSON.parse(result);
        return promisify('http://jsonplaceholder.typicode.com/users/' + obj.userId + '/albums')
    })
    .catch(function (e) {
        console.log(e);
    })
    .then(function (result) {
        res.end(result);
    })
})

var server = app.listen(8081, function () {
    var host = server.address().address
    var port = server.address().port

    console.log("Beispiel-App hört unter http://%s:%s zu", host, port)
})

// Webservice im Browser ausführen: http://localhost:8081/listAlbums

8voto

Jason Loveman Punkte 655

Die Q-Bibliothek von kriskowal enthält Callback-to-Promise-Funktionen. Eine Methode wie diese:

obj.prototype.dosomething(params, cb) {
  ...blah blah...
  cb(error, results);
}

kann mit Q.ninvoke konvertiert werden

Q.ninvoke(obj,"dosomething",params).
then(function(results) {
});

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X