Làm cách nào để chuyển đổi API gọi lại hiện có thành các hứa hẹn?

747
Benjamin Gruenbaum 2014-03-20 12:47.

Tôi muốn làm việc với các lời hứa nhưng tôi có một API gọi lại ở định dạng như:

1. Tải DOM hoặc sự kiện diễn ra một lần khác:

window.onload; // set to callback
...
window.onload = function() {

};

2. Gọi lại thuần túy:

function request(onChangeHandler) {
    ...
}
request(function() {
    // change happened
    ...
});

3. Gọi lại kiểu nút ("nodeback"):

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

4. Toàn bộ thư viện với các lệnh gọi lại kiểu nút:

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

Làm cách nào để làm việc với API trong các lời hứa, làm cách nào để "quảng bá" nó?

19 answers

769
Benjamin Gruenbaum 2014-03-20 12:47.

Lời hứa có trạng thái, chúng bắt đầu ở dạng đang chờ xử lý và có thể giải quyết thành:

  • hoàn thành nghĩa là tính toán đã hoàn tất thành công.
  • bị từ chối nghĩa là tính toán không thành công.

Các hàm trả về Promise không bao giờ được ném ra , thay vào đó chúng sẽ trả về các hàm từ chối. Việc ném từ một hàm trả về lời hứa sẽ buộc bạn phải sử dụng cả a } catch { a .catch. Những người sử dụng API quảng cáo không mong đợi những lời hứa sẽ được thực hiện. Nếu bạn không chắc về cách hoạt động của các API không đồng bộ trong JS - trước tiên hãy Làm cách nào để trả lại phản hồi từ cuộc gọi không đồng bộ? .

1. Tải DOM hoặc sự kiện diễn ra một lần khác:

Vì vậy, việc tạo lời hứa nói chung có nghĩa là chỉ định thời điểm chúng giải quyết - nghĩa là khi chúng chuyển sang giai đoạn được thực hiện hoặc bị từ chối để cho biết dữ liệu có sẵn (và có thể được truy cập bằng .then).

Với các triển khai hứa hẹn hiện đại hỗ trợ phương thức Promisekhởi tạo như các hứa hẹn ES6 bản địa:

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

Sau đó, bạn sẽ sử dụng lời hứa kết quả như sau:

load().then(function() {
    // Do things after onload
});

Với các thư viện hỗ trợ hoãn lại (Hãy sử dụng $ q cho ví dụ này ở đây, nhưng chúng ta cũng sẽ sử dụng jQuery sau):

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

Hoặc với một jQuery như API, kết nối sự kiện xảy ra một lần:

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

2. Gọi lại thuần túy:

Các API này khá phổ biến vì… các lệnh gọi lại rất phổ biến trong JS. Hãy xem xét trường hợp phổ biến của việc có onSuccessonFail:

function getUserData(userId, onLoad, onFail) { …

Với các triển khai hứa hẹn hiện đại hỗ trợ phương thức Promisekhởi tạo như các hứa hẹn ES6 bản địa:

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

Với các thư viện hỗ trợ hoãn lại (Hãy sử dụng jQuery cho ví dụ này ở đây, nhưng chúng tôi cũng đã sử dụng $ q ở trên):

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

jQuery cũng cung cấp một $.Deferred(fn)biểu mẫu, có ưu điểm là cho phép chúng ta viết một biểu thức mô phỏng rất chặt chẽ new Promise(fn)biểu mẫu, như sau:

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

Lưu ý: Ở đây chúng tôi khai thác thực tế rằng jQuery được hoãn lại resolverejectcác phương thức là "có thể tháo rời"; I E. chúng được liên kết với thể hiện của jQuery.Deferred (). Không phải tất cả các lib đều cung cấp tính năng này.

3. Gọi lại kiểu nút ("nodeback"):

Các lệnh gọi lại kiểu nút (nodeback) có một định dạng cụ thể trong đó các lệnh gọi lại luôn là đối số cuối cùng và tham số đầu tiên của nó là một lỗi. Trước tiên, hãy làm nổi bật một thủ công:

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

Đến:

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

Với việc trả chậm, bạn có thể làm như sau (hãy sử dụng Q cho ví dụ này, mặc dù Q hiện hỗ trợ cú pháp mới mà bạn nên thích ):

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;   
}

Nói chung, bạn không nên quảng bá mọi thứ theo cách thủ công quá nhiều, hầu hết các thư viện hứa hẹn được thiết kế với Node trong tâm trí cũng như các hứa hẹn gốc trong Node 8+ đều có một phương thức tích hợp để quảng bá các nodeback. Ví dụ

var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only

4. Toàn bộ thư viện với các lệnh gọi lại kiểu nút:

Không có quy tắc vàng nào ở đây, bạn chỉ ra từng cái một. Tuy nhiên, một số triển khai hứa hẹn cho phép bạn thực hiện điều này hàng loạt, chẳng hạn như trong Bluebird, việc chuyển đổi một API nodeback thành một API hứa hẹn đơn giản như:

Promise.promisifyAll(API);

Hoặc với các lời hứa ban đầu trong 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}), {});

Ghi chú:

  • Tất nhiên, khi bạn đã .thennắm trong tay, bạn không cần phải quảng bá mọi thứ. Việc trả lại lời hứa từ người .thenxử lý sẽ giải quyết hoặc từ chối với giá trị của lời hứa đó. Ném từ một người .thenđiều khiển cũng là một thực hành tốt và sẽ từ chối lời hứa - đây là cách an toàn khi ném lời hứa nổi tiếng.
  • Trong onloadtrường hợp thực tế , bạn nên sử dụng addEventListenerhơn là onX.
58
efkan 2017-01-03 03:19.

Hôm nay, tôi có thể sử dụng Promisetrong Node.jsnhư một phương thức Javascript đơn giản.

Một ví dụ đơn giản và cơ bản về Promise(với cách KISS ):

Mã API không đồng bộ Javascript thuần:

function divisionAPI (number, divider, successCallback, errorCallback) {

    if (divider == 0) {
        return errorCallback( new Error("Division by zero") )
    }

    successCallback( number / divider )

}

Promise Mã API không đồng bộ Javascript:

function divisionAPI (number, divider) {

    return new Promise(function (fulfilled, rejected) {

        if (divider == 0) {
            return rejected( new Error("Division by zero") )
        }

        fulfilled( number / divider )

     })

}

(Tôi khuyên bạn nên ghé thăm nguồn tuyệt đẹp này )

Cũng Promisecó thể được sử dụng với cùng nhau async\awaittrong ES7để làm cho dòng chương trình đợi fullfiledkết quả như sau:

function getName () {

    return new Promise(function (fulfilled, rejected) {

        var name = "John Doe";

        // wait 3000 milliseconds before calling fulfilled() method
        setTimeout ( 
            function() {
                fulfilled( name )
            }, 
            3000
        )

    })

}


async function foo () {

    var name = await getName(); // awaits for a fulfilled result!

    console.log(name); // the console writes "John Doe" after 3000 milliseconds

}


foo() // calling the foo() method to run the code

Một cách sử dụng khác với cùng một mã bằng cách sử dụng .then()phương pháp

function getName () {

    return new Promise(function (fulfilled, rejected) {

        var name = "John Doe";

        // wait 3000 milliseconds before calling fulfilled() method
        setTimeout ( 
            function() {
                fulfilled( name )
            }, 
            3000
        )

    })

}


// the console writes "John Doe" after 3000 milliseconds
getName().then(function(name){ console.log(name) })

Promisecũng có thể được sử dụng trên bất kỳ nền tảng nào dựa trên Node.js như react-native.

Phần thưởng : Một phương thức kết hợp
( Phương thức gọi lại được giả định có hai tham số là lỗi và kết quả)

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 )

     })

}

Phương thức trên có thể trả lời kết quả cho các sử dụng kiểu cũ và Promise.

Hi vọng điêu nay co ich.

35
Siva Kannan 2017-08-12 01:31.

Trước khi chuyển đổi một hàm như lời hứa Trong Node.JS

var request = require('request'); //http wrapped module

function requestWrapper(url, callback) {
    request.get(url, function (err, response) {
      if (err) {
        callback(err);
      }else{
        callback(null, response);             
      }      
    })
}


requestWrapper(url, function (err, response) {
    console.log(err, response)
})

Sau khi chuyển đổi nó

var request = require('request');

function requestWrapper(url) {
  return new Promise(function (resolve, reject) { //returning promise
    request.get(url, function (err, response) {
      if (err) {
        reject(err); //promise reject
      }else{
        resolve(response); //promise resolve
      }
    })
  })
}


requestWrapper('http://localhost:8080/promise_request/1').then(function(response){
    console.log(response) //resolve callback(success)
}).catch(function(error){
    console.log(error) //reject callback(failure)
})

Trong trường hợp bạn cần xử lý nhiều yêu cầu

var allRequests = [];
allRequests.push(requestWrapper('http://localhost:8080/promise_request/1')) 
allRequests.push(requestWrapper('http://localhost:8080/promise_request/2'))
allRequests.push(requestWrapper('http://localhost:8080/promise_request/5'))    

Promise.all(allRequests).then(function (results) {
  console.log(results);//result will be array which contains each promise response
}).catch(function (err) {
  console.log(err)
});
23
Leo 2015-01-14 18:15.

Tôi không nghĩ rằng window.onloadđề xuất của @Benjamin sẽ hoạt động mọi lúc, vì nó không phát hiện liệu nó có được gọi sau khi tải hay không. Tôi đã bị nó cắn nhiều lần. Đây là một phiên bản luôn hoạt động:

function promiseDOMready() {
    return new Promise(function(resolve) {
        if (document.readyState === "complete") return resolve();
        document.addEventListener("DOMContentLoaded", resolve);
    });
}
promiseDOMready().then(initOnLoad);
15
Gian Marco 2017-05-31 20:46.

Node.js 8.0.0 bao gồm một util.promisify()API mới cho phép các API kiểu gọi lại Node.js tiêu chuẩn được bao bọc trong một hàm trả về một Lời hứa. Một ví dụ sử dụng util.promisify()được hiển thị bên dưới.

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

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

readFile('/some/file')
  .then((data) => { /** ... **/ })
  .catch((err) => { /** ... **/ });

Xem Hỗ trợ được cải thiện cho Lời hứa

14
Bruno 2017-05-16 19:35.

Trong ứng cử viên phát hành cho Node.js 8.0.0, có một tiện ích mới, util.promisify(tôi đã viết về use.promisify ), đóng gói khả năng quảng bá bất kỳ chức năng nào.

Nó không khác nhiều so với các cách tiếp cận được đề xuất trong các câu trả lời khác, nhưng có lợi thế là một phương pháp cốt lõi và không yêu cầu phụ thuộc bổ sung.

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

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

Sau đó, bạn có một readFilephương thức trả về một giá trị gốc Promise.

readFile('./notes.txt')
  .then(txt => console.log(txt))
  .catch(...);
7
Apoorv 2016-06-21 03:38.

Bạn có thể sử dụng các hứa hẹn gốc JavaScript với Node JS.

Liên kết mã Cloud 9 của tôi: https://ide.c9.io/adx2803/native-promises-in-node

/**
* Created by dixit-lab on 20/6/16.
*/

var express = require('express');
var request = require('request');   //Simplified HTTP request client.


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);
            }
        })
    });
}

//get all the albums of a user who have posted post 100
app.get('/listAlbums', function (req, res) {
    //get the post with post id 100
    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("Example app listening at http://%s:%s", host, port)
})

//run webservice on browser : http://localhost:8081/listAlbums
7
daviddavis 2016-11-28 17:07.

Với javaScript vani cũ đơn giản, đây là một giải pháp để kích hoạt một lệnh gọi lại api.

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('successful ... should call callback ... ');
                    callback(null, JSON.parse(xhr.responseText));
                } else {
                    console.log('error ... callback with error data ... ');
                    callback(xhr, null);
                }
            }
        });
        xhr.send();
    }

/**
     * @function promisify: convert api based callbacks to promises
     * @description takes in a factory function and promisifies it
     * @params {function} input function to promisify
     * @params {array} an array of inputs to the function to be promisified
     * @return {function} promisified function
     * */
    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) {
        // corresponds to the resolve function
        console.log('successful operation: ', data);
}, function (error) {
        console.log(error);
});
6
Jason Loveman 2015-04-08 08:30.

Thư viện Q của kriskowal bao gồm các hàm gọi lại để hứa. Một phương pháp như thế này:

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

có thể được chuyển đổi bằng Q.ninvoke

Q.ninvoke(obj,"dosomething",params).
then(function(results) {
});
4
user1852503 2016-08-04 14:45.

Khi bạn có một vài hàm thực hiện cuộc gọi lại và bạn muốn chúng trả về một lời hứa thay vào đó, bạn có thể sử dụng hàm này để thực hiện chuyển đổi.

function callbackToPromise(func){

    return function(){

        // change this to use what ever promise lib you are using
        // In this case i'm using angular $q that I exposed on a util module

        var defered = util.$q.defer();

        var cb = (val) => {
            defered.resolve(val);
        }

        var args = Array.prototype.slice.call(arguments);
        args.push(cb);    
        func.apply(this, args);

        return defered.promise;
    }
}
4
Paul Spaulding 2017-04-13 06:48.

Trong nút v7.6 + đã được tích hợp sẵn các hứa hẹn và không đồng bộ:

// promisify.js
let promisify = fn => (...args) =>
    new Promise((resolve, reject) =>
        fn(...args, (err, result) => {
            if (err) return reject(err);
            return resolve(result);
        })
    );

module.exports = promisify;

Cách sử dụng:

let readdir = require('fs').readdir;
let promisify = require('./promisify');
let readdirP = promisify(readdir);

async function myAsyncFn(path) {
    let entries = await readdirP(path);
    return entries;
}
3
Do Async 2017-10-13 12:19.

Trong Node.js 8, bạn có thể quảng bá các phương thức đối tượng một cách nhanh chóng bằng cách sử dụng mô-đun npm này:

https://www.npmjs.com/package/doasync

Nó sử dụng use.promisifyProxy để các đối tượng của bạn không thay đổi. Ghi nhớ cũng được thực hiện với việc sử dụng WeakMaps). Dưới đây là một số ví dụ:

Với các đối tượng:

const fs = require('fs');
const doAsync = require('doasync');

doAsync(fs).readFile('package.json', 'utf8')
  .then(result => {
    console.dir(JSON.parse(result), {colors: true});
  });

Với các chức năng:

doAsync(request)('http://www.google.com')
  .then(({body}) => {
    console.log(body);
    // ...
  });

Bạn thậm chí có thể sử dụng bản địa callapplyđể ràng buộc một số ngữ cảnh:

doAsync(myFunc).apply(context, params)
  .then(result => { /*...*/ });
2
Nicolas Zozol 2017-01-23 03:22.

Bạn có thể sử dụng Promise gốc trong ES6, để xử lý ví dụ với setTimeout:

enqueue(data) {

    const queue = this;
    // returns the Promise
    return new Promise(function (resolve, reject) {
        setTimeout(()=> {
                queue.source.push(data);
                resolve(queue); //call native resolve when finish
            }
            , 10); // resolve() will be called in 10 ms
    });

}

Trong ví dụ này, Lời hứa không có lý do gì để thất bại, vì vậy reject()không bao giờ được gọi.

2
jituanlin 2017-07-31 03:39.

Hàm kiểu gọi lại luôn như thế này (hầu như tất cả hàm trong node.js là kiểu này):

//fs.readdir(path[, options], callback)
fs.readdir('mypath',(err,files)=>console.log(files))

Phong cách này có cùng một tính năng:

  1. hàm gọi lại được truyền bởi đối số cuối cùng.

  2. hàm gọi lại luôn chấp nhận đối tượng lỗi vì nó là đối số đầu tiên.

Vì vậy, bạn có thể viết một hàm để chuyển đổi một hàm với kiểu như thế này:

const R =require('ramda')

/**
 * A convenient function for handle error in callback function.
 * Accept two function res(resolve) and rej(reject) ,
 * return a wrap function that accept a list arguments,
 * the first argument as error, if error is null,
 * the res function will call,else the rej function.
 * @param {function} res the function which will call when no error throw
 * @param {function} rej the function which will call when  error occur
 * @return {function} return a function that accept a list arguments,
 * the first argument as error, if error is null, the res function
 * will call,else the rej function
 **/
const checkErr = (res, rej) => (err, ...data) => R.ifElse(
    R.propEq('err', null),
    R.compose(
        res,
        R.prop('data')
    ),
    R.compose(
        rej,
        R.prop('err')
    )
)({err, data})

/**
 * wrap the callback style function to Promise style function,
 * the callback style function must restrict by convention:
 * 1. the function must put the callback function where the last of arguments,
 * such as (arg1,arg2,arg3,arg...,callback)
 * 2. the callback function must call as callback(err,arg1,arg2,arg...)
 * @param {function} fun the callback style function to transform
 * @return {function} return the new function that will return a Promise,
 * while the origin function throw a error, the Promise will be Promise.reject(error),
 * while the origin function work fine, the Promise will be Promise.resolve(args: array),
 * the args is which callback function accept
 * */
 const toPromise = (fun) => (...args) => new Promise(
    (res, rej) => R.apply(
        fun,
        R.append(
            checkErr(res, rej),
            args
        )
    )
)

Để ngắn gọn hơn, ví dụ trên đã sử dụng ramda.js. Ramda.js là một thư viện tuyệt vời để lập trình chức năng. Trong đoạn mã trên, chúng tôi sử dụng nó là apply (như javascript function.prototype.apply) và append (như javascript function.prototype.push). Vì vậy, chúng ta có thể chuyển đổi hàm kiểu gọi lại thành hàm kiểu hứa ngay bây giờ:

const {readdir} = require('fs')
const readdirP = toPromise(readdir)
readdir(Path)
    .then(
        (files) => console.log(files),
        (err) => console.log(err)
    )

Hàm toPromisecheckErr thuộc sở hữu của thư viện berserk , nó là một nhánh thư viện lập trình chức năng của ramda.js (do tôi tạo).

Hy vọng câu trả lời này hữu ích cho bạn.

2
onmyway133 2018-10-10 03:35.

Bạn có thể làm điều gì đó như thế này

// @flow

const toPromise = (f: (any) => void) => {
  return new Promise<any>((resolve, reject) => {
    try {
      f((result) => {
        resolve(result)
      })
    } catch (e) {
      reject(e)
    }
  })
}

export default toPromise

Sau đó sử dụng nó

async loadData() {
  const friends = await toPromise(FriendsManager.loadFriends)

  console.log(friends)
}
1
Pujan 2017-10-18 13:56.

es6-promisify chuyển đổi các hàm dựa trên cuộc gọi lại thành các hàm dựa trên Promise.

const promisify = require('es6-promisify');

const promisedFn = promisify(callbackedFn, args);

Tham khảo: https://www.npmjs.com/package/es6-promisify

1
loretoparisi 2017-11-30 13:34.

Phiên bản quảng bá của tôi về một callbackhàm là Phàm:

var P = function() {
  var self = this;
  var method = arguments[0];
  var params = Array.prototype.slice.call(arguments, 1);
  return new Promise((resolve, reject) => {
    if (method && typeof(method) == 'function') {
      params.push(function(err, state) {
        if (!err) return resolve(state)
        else return reject(err);
      });
      method.apply(self, params);
    } else return reject(new Error('not a function'));
  });
}
var callback = function(par, callback) {
  var rnd = Math.floor(Math.random() * 2) + 1;
  return rnd > 1 ? callback(null, par) : callback(new Error("trap"));
}

callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))

P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))

Các Pchức năng yêu cầu chữ ký callback phải là callback(error,result).

1
Mzndako 2019-06-22 00:38.

Dưới đây là cách triển khai một hàm (API gọi lại) có thể được chuyển đổi thành một lời hứa.

function promisify(functionToExec) {
  return function() {
    var array = Object.values(arguments);
    return new Promise((resolve, reject) => {
      array.push(resolve)
      try {
         functionToExec.apply(null, array);
      } catch (error) {
         reject(error)
      }
    })
  }
}

// USE SCENARIO

function apiFunction (path, callback) { // Not a promise
  // Logic
}

var promisedFunction = promisify(apiFunction);

promisedFunction('path').then(()=>{
  // Receive the result here (callback)
})

// Or use it with await like this
let result = await promisedFunction('path');

1
Josiah Nyarega 2020-09-25 08:28.

Từ tương lai 😄

Một hàm chung đơn giản mà tôi thường sử dụng.

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

Làm thế nào để sử dụng nó

   promisify(fn, arg1, arg2)

Bạn có thể không tìm câu trả lời này, nhưng điều này sẽ giúp hiểu hoạt động bên trong của các utils có sẵn

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Xem đoạn giới thiệu cho bộ phim chuyển thể đầy khói lửa, có sự góp mặt của ngôi sao Edward Norton từ phim Motherless Brooklyn của Jonathan Lethem

Xem đoạn giới thiệu cho bộ phim chuyển thể đầy khói lửa, có sự góp mặt của ngôi sao Edward Norton từ phim Motherless Brooklyn của Jonathan Lethem

Edward Norton đã muốn đưa cuốn tiểu thuyết Motherless Brooklyn của Jonathan Lethem's Joycean 1999 lên màn ảnh kể từ khi nó được xuất bản. Bây giờ, 20 năm sau, một đoạn giới thiệu đã xuất hiện cho câu chuyện sôi nổi, đưa câu chuyện của Lethem trở lại những năm 1950 với rất nhiều gương mặt quen thuộc.

Cách dễ dàng chọn không tham gia trọng tài ràng buộc thẻ Apple

Cách dễ dàng chọn không tham gia trọng tài ràng buộc thẻ Apple

Có thích thú khi sử dụng Thẻ Apple mới của bạn không? Trước khi bạn bắt đầu chi tiêu, có một nhiệm vụ bổ sung cần xem xét: chọn không tham gia trọng tài ràng buộc. Bạn sẽ phát hiện ra các điều khoản trọng tài ràng buộc trong nhiều thỏa thuận tài chính vì nó giúp ngăn các ngân hàng và đối tác kinh doanh của họ không phải ra tòa.

Những người chơi Fortnite World Cup không ghi bàn có cảm giác hài hước về điều đó

Những người chơi Fortnite World Cup không ghi bàn có cảm giác hài hước về điều đó

Điểm số tại vòng chung kết Fortnite World Cup Solo hôm nay là rất lớn, với người chiến thắng Bugha ghi được nhiều hơn 26 điểm so với người về thứ hai là Psalm. Nhưng không phải ai cũng có thể giành chiến thắng: Bốn cầu thủ ra về với 0 điểm, nhưng — ít nhất là trên Twitter — họ là những người thể thao tốt về điều đó.

Báo cáo: Cánh cửa tuyển sinh có thể đã mở cho các ứng viên UCLA có mối quan hệ có ảnh hưởng

Báo cáo: Cánh cửa tuyển sinh có thể đã mở cho các ứng viên UCLA có mối quan hệ có ảnh hưởng

Huấn luyện viên trưởng của bộ môn thể dục dụng cụ UCLA Valorie Kondos-Field theo dõi Katelyn Ohashi thi đấu thăng bằng trong trận gặp Stanford tại Pauley Pavilion vào ngày 10 tháng 3 năm 2019 ở Los Angeles, California. Vụ bê bối gian lận tuyển sinh đại học tiết lộ các chi tiết của một quá trình chính thức hóa để đưa những đứa trẻ thất bại của các gia đình giàu có và nổi tiếng vào các trường đại học đáng tin cậy và danh tiếng, sử dụng một "cửa phụ" đắt tiền cho các bậc cha mẹ mà sự giàu có của họ khiến họ không có cơ hội. chỉ cần tài trợ cho một cánh mới trong khuôn viên trường.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Tầm nhìn đám mây phi tập trung của DFINITY Blockchain

Lưu ý của người biên tập: Bạn đang xem tài liệu lỗi thời từ blog DFINITY đang được bảo quản cho mục đích lưu trữ.

Tầm nhìn đám mây phi tập trung của DFINITY Blockchain

Bài đăng này khám phá tầm nhìn về đám mây phi tập trung của nhóm DFINITY và cách nó liên quan đến các nhà cung cấp blockchain truyền thống và đám mây hiện có như Amazon Web Services. Các minh chứng về công nghệ DFINITY được áp dụng bởi một mạng lưới quy mô lớn sẽ được thực hiện vào mùa thu năm 2017, sau đó sẽ được gây quỹ Chính cho quỹ hỗ trợ phi lợi nhuận, với mạng “đám mây mở” dự kiến ​​sẽ ra mắt vào đầu mùa hè năm 2018 .

Language